/**
 * 表格功能封装,采用动态切换table实例的table元素机制，整个富文本只有一个Table实例
 * by kevin.huang
 * * */
class Table extends $B.BaseControl {
    constructor(editIns) {
        super();
        this.splitNearVal = 4;
        this.selectedTdArray = [];
        this.cssPelist = [];
        this.minRowHeight = 10;
        this.mutilSelect = false;
        this.editIns = editIns;
        var _this = this;
        this.colorIns = editIns.getColorIns("tableColor", function (hex, opacity) {            
            _this.$colorEL.style.backgroundColor = hex;
            clearTimeout(_this.exeColorTimer);
            _this.exeColorTimer = setTimeout(() => {
                _this[_this.colorCaller]({ color: hex, opacity: opacity });
            }, 300);
        });
    }
    exeCss(fn, params, eventEl) {
        if (params && (params.color
            || params["border-top"]
            || params["border-right"]
            || params["border-bottom"]
            || params["border-left"]
            || params["background-color"])) {
            this.holdColorCtl = true;
        }
        this.hidePanel();
        this.holdColorCtl = false;
        if (this.editIns.isSelected()) {
            if (fn !== "ppadding" && fn !== "plineHeight"
                && fn !== "pborderFn" && fn !== "pindentFn"
                && fn !== "pcolorFn" && fn !== "pbackground"
            ) {
                return true;
            }
        }       
        if (this.clickedTd && typeof this[fn] === "function") {
            let table = this.getTableByTd(this.clickedTd);
            this.setTarget(table);
            let ret = false;
            //先生成一个撤销记录
            let prtEl = this.getRootPelByTable(table);
            this.editIns.makeUndoData(prtEl);
            let r = this[fn](params, eventEl);
            if (typeof r !== "undefined") {
                ret = r;
            }            
            if(r){
                this.editIns.clearUndoingData();
            }else{
                //插入一个撤销记录
                this.editIns.putUndoData(1);
            }
            return ret;
        }
        return true;
    }
    activedLinePELS() {
        let plist = [];
        if (this.isSelectedTds()) {
            this.foreachSeletedTds((td) => {
                this.extractTdPel(td, plist);
            });
        } else {
            if (this.editIns.isSelected()) {
                //console.log(this.editIns.cssPEls);
                let els = this.clickedTd.firstChild.firstChild.children;
                let startPelId = this.editIns.region.dirStrtId;
                let endPelId = this.editIns.region.dirEndId;
                for (let i = 0; i < els.length; i++) {
                    if (els[i].id === startPelId) {
                        plist.push(els[i]);
                        break;
                    }
                }
                if (startPelId !== endPelId) {
                    let nextp = plist[0].nextSibling;
                    while (nextp) {
                        plist.push(nextp);
                        if (nextp.id === endPelId) {
                            break;
                        }
                    }
                }
            } else {
                this.extractTdPel(this.clickedTd, plist);
            }
        }
        this.cssPelist = plist;
        for (let i = 0; i < this.cssPelist.length; i++) {
            $B.DomUtils.addClass(this.cssPelist[i], "k_editor_actived_section");
        }
        this.graphOpening = true;
    }
    unactivedLinePELS() {
        this.graphOpening = false;
        for (let i = 0; i < this.cssPelist.length; i++) {
            $B.DomUtils.removeClass(this.cssPelist[i], "k_editor_actived_section");
        }
        this.cssPelist = [];
    }
    resetCss(tabel){
       let trs = tabel.firstChild.children;
       for(let i =0 ; i < trs.length ;i++){
            let tr = trs[i];
            let tds = tr.children;
            for(let j =0 ;j < tds.length ;j++){
                let $wap = tds[j].firstChild.firstChild;
                if($wap.children.length === 1 && $wap.firstChild.firstChild.nodeName === "TABLE"){
                    this.resetCss($wap.firstChild.firstChild);
                }else{
                    let plist = $wap.children;
                    for(let p =0 ; p < plist.length ;p++){
                        let $p = plist[p];
                        $B.Dom.attr($p,{style: editCfg.pElementCss});
                        let $sps = $p.children;
                        for(let k =  0; k < $sps.length ;k++){
                            $B.Dom.attr($sps[k],{style: editCfg.spanCss});
                        }
                    }
                }
            }
       }
    }
    forPels(fn) {
        for (let i = 0; i < this.cssPelist.length; i++) {
            fn(this.cssPelist[i]);
        }
    }
    extractTdPel(td, plist) {
        let childs = td.firstChild.firstChild.children;
        for (let i = 0; i < childs.length; i++) {
            plist.push(childs[i]);
        }
    }
    setTarget(el) {
        this.tableEl = el;
    }
    clearTarget() {
        this.tableEl = undefined;
    }
    clearClickTd() {
        if (this.clickedTd) {
            $B.DomUtils.removeClass(this.clickedTd, 'k_edit_selected_td_shadow');
            this.clickedTd = undefined;
        }
    }
    setClickTd(td) {
        this.clearClickTd();
        $B.DomUtils.addClass(td, "k_edit_selected_td_shadow");
        if(td.nodeName !== "TD"){
            console.log("set k_edit_selected_td_shadow");
        }
        this.clickedTd = td;
    }
    isEmptyTd(td) {
        let $wap = td.firstChild.firstChild;
        let childs = $wap.children;
        for (let i = 0; i < childs.length; i++) {
            let p = childs[i];
            if (p.firstChild && p.firstChild.nodeName === "TABLE") {
                return false;
            }
            if (p.innerText.replaceAll("\u200b", "") !== "") {
                return false;
            }
        }
        return true;
    }
    getTdKey(td) {
        return $B.DomUtils.attribute(td, "row") + "_" + $B.DomUtils.attribute(td, "col");
    }
    getFocusEl(tabEl) {
        let tr = tabEl.firstChild.firstChild;
        let ret = this.getFocusElFromTd(tr.firstChild);
        if (ret) {
            return ret;
        }
        tr = tr.nextSibling;
        while (tr) {
            ret = this.getFocusElFromTr(tr.firstChild);
            if (ret) {
                break;
            }
            tr = tr.nextSibling;
        }
        return ret;
    }
    getFocusElFromTd(td) {
        let el = td.firstChild.firstChild;
        let ret;
        while (el) {
            if ($B.DomUtils.hasClass(el, "p_span")) {
                ret = el;
                break;
            }
            el = el.firstChild;
        }
        if (ret) {
            return ret;
        }
        let nextTd = td.nextSibling;
        while (nextTd) {
            ret = this.getFocusElFromTd(nextTd);
            if (ret) {
                break;
            }
            nextTd = nextTd.nextSibling;
        }
        return ret;
    }
    focusTable(tabEl) {
        let firstSpan = this.getFocusEl(tabEl);
        this.editIns.move2end(firstSpan);
        return firstSpan;
    }
    focusTd(td) {
        if (!td) {
            td = this.clickedTd;
        }
        if (td) {
            this.editIns.move2start(td.firstChild.firstChild.firstChild);
        }
    }
    getTableByTd(td) {
        let $p = td.parentNode;
        while ($p) {
            if ($p.nodeName === "TABLE") {
                break;
            }
            $p = $p.parentNode;
        }
        return $p;
    }
    getRootPelByTd(td){
        let tabEL = this.getTableByTd(td);
        return this.getRootPelByTable(tabEL);
    }
    getRootPelByTable(tabEL){
        let prtEl = tabEL.parentNode;
        while(prtEl){
            if($B.Dom.hasClass(prtEl,"p_element")){
                if($B.Dom.hasClass(prtEl.parentNode,"k_edit_input")){
                    break;
                }
            }
            prtEl = prtEl.parentNode;
        }
        return prtEl;
    }
    getTableByTr(tr) {
        return this.getTableByTd(tr);
    }
    changeCursor(cursor) {
        if (this.tableEl) {
            this.changeTableCursor(this.tableEl, cursor);
        }
    }
    changeTableCursor(tableEl, cursor) {
        this.foreachTd(tableEl, (td) => {
            td.style.cursor = cursor;
            let wrap = td.firstChild.firstChild;
            let childs = wrap.children;
            for (let i = 0; i < childs.length; i++) {
                childs[i].style.cursor = cursor;
            }
        });
    }
    foreachTd(tableEl, fn) {
        var trs = tableEl.firstChild.children;
        for (let i = 0; i < trs.length; i++) {
            let tr = trs[i];
            let tds = tr.children;
            let isLastRow = i === trs.length - 1;
            for (let j = 0; j < tds.length; j++) {
                let args = {
                    rowNum: i,
                    colNum: j,
                    isLastRow: isLastRow,
                    islastCol: j === tds.length - 1
                };
                fn(tds[j], args);
            }
        }
    }
    clearSelected(clearALl) {
        for (let i = 0; i < this.selectedTdArray.length; i++) {
            $B.DomUtils.removeClass(this.selectedTdArray[i], 'k_edit_td_selected');
        }
        this.selectedTdArray = [];
        if (clearALl && this.clickedTd) {
            if (clearALl) {
                this.clearClickTd();
            }
        }
    }
    onRemoved() {
        this.clickedTd = undefined;
        this.selectedTdArray = [];
    }
    isSelectedTds() {
        return this.selectedTdArray.length > 0;
    }
    foreachSeletedTds(fn) {
        for (let i = 0; i < this.selectedTdArray.length; i++) {
            fn(this.selectedTdArray[i]);
        }
        return this.selectedTdArray.length > 0;
    }
    cancelMutilSelect() {
        this.mutilSelect = false;
    }
    makeSelectedUi() {
        if (!this.clickedTd) {
            return;
        }
        var row0 = parseInt($B.DomUtils.attribute(this.clickedTd, "row"));
        var col0 = parseInt($B.DomUtils.attribute(this.clickedTd, "col"));
        var row1 = parseInt($B.DomUtils.attribute(this.movingTd, "row"));
        var col1 = parseInt($B.DomUtils.attribute(this.movingTd, "col"));
        var rowspan = $B.DomUtils.attribute(this.movingTd, "rowspan");
        var colspan = $B.DomUtils.attribute(this.movingTd, "colspan");
        if (rowspan) {
            row1 = row1 + parseInt(rowspan) - 1;
        }
        if (colspan) {
            col1 = col1 + parseInt(colspan) - 1;
        }
        this.clearSelected();
        var startRow, startCol, endRow, endCol;
        if (row1 > row0) {
            startRow = row0;
            endRow = row1;
        } else {
            startRow = row1;
            endRow = row0;
        }
        if (col1 > col0) {
            startCol = col0;
            endCol = col1;
        } else {
            startCol = col1;
            endCol = col0;
        }
        this.foreachAddSelected(startRow, endRow, startCol, endCol);
    }
    foreachAddSelected(startRow, endRow, startCol, endCol) {
        let trs = this.getTableByTd(this.clickedTd).firstChild.children;
        let maxRow = endRow,
            maxCol = endCol,
            tdArr = [];
        for (let i = 0; i < trs.length; i++) {
            if (i < startRow || i > endRow) {
                continue;
            }
            let tds = trs[i].children;
            for (let j = 0; j < tds.length; j++) {
                let td = tds[j];
                let colIdx = parseInt($B.DomUtils.attribute(td, "col"));
                if (colIdx < startCol || colIdx > endCol) {
                    continue;
                }
                tdArr.push(td);
                $B.DomUtils.addClass(td, "k_edit_td_selected");
                this.selectedTdArray.push(td);
            }
        }
        for (let i = 0; i < tdArr.length; i++) {
            let td = tdArr[i];
            if (td !== this.movingTd && td !== this.clickedTd) {
                let rowSpan = $B.Dom.attr(td, "rowspan");
                let colSpan = $B.Dom.attr(td, "colspan");
                if (rowSpan || colSpan) {
                    if (rowSpan) {
                        let tmpV = parseInt($B.Dom.attr(td, "row")) + parseInt(rowSpan) - 1;
                        if (tmpV > maxRow) {
                            maxRow = tmpV;
                        }
                    }
                    if (colSpan) {
                        let tmpV = parseInt($B.Dom.attr(td, "col")) + parseInt(colSpan) - 1;
                        if (tmpV > maxCol) {
                            maxCol = tmpV;
                        }
                    }
                }
            }
        }
        if (maxRow !== endRow || maxCol !== endCol) {
            endRow = maxRow;
            endCol = maxCol;
            this.clearSelected();
            for (let i = 0; i < trs.length; i++) {
                if (i < startRow || i > endRow) {
                    continue;
                }
                let tds = trs[i].children;
                for (let j = 0; j < tds.length; j++) {
                    let td = tds[j];
                    let colIdx = parseInt($B.DomUtils.attribute(td, "col"));
                    if (colIdx < startCol || colIdx > endCol) {
                        continue;
                    }
                    $B.DomUtils.addClass(td, "k_edit_td_selected");
                    this.selectedTdArray.push(td);
                }
            }
        }
    }
    /**
     * 插入子表格时候适配 父单元格
     * ***/
    fit2parent(tableEl) {
        let $containTd = tableEl.parentNode.parentNode;
        if ($B.DomUtils.hasClass($containTd, "k_edit_input")) {
            return;
        }
        $containTd = $containTd.parentNode.parentNode;
        if ($containTd && $containTd.nodeName === "TD") {
            tableEl.style.width = "100%";
            tableEl.style.height = "100%";
            this.setWnHFromDom(tableEl);
            tableEl.style.width = "auto";
            tableEl.style.height = "auto";
        }
        return true;
    }
    /**
     * 提取dom里面的高度，宽度，并设置到td上
     * **/
    setWnHFromDom(tableEl) {
        this.foreachTd(tableEl, (td) => {
            this._updateTdSizeFromDom(td);
        });
        tableEl.style.width = "auto";
        tableEl.style.height = "auto";
    }
    /**
     * 提取Dom里面的高度，宽度更新行高度
     * ***/
    updateRowWnHFromDom(tr) {
        let tds = tr.children;
        for (let i = 0; i < tds.length; i++) {
            let td = tds[i];
            this._updateTdSizeFromDom(td);
        }
        let $pt = tr.parentNode.parentNode.parentNode.parentNode.parentNode;
        if ($pt.nodeName === "TD") { //多层嵌套
            this.updateRowWnHFromDom($pt.parentNode);
        }
    }
    _updateTdSizeFromDom(td) {
        let w = $B.DomUtils.width(td);
        let h = $B.DomUtils.height(td);
        let size = { width: w, height: h };
        let inW = $B.DomUtils.innerWidth(td);
        let inH = $B.DomUtils.innerHeight(td);
        $B.DomUtils.css(td.firstChild, { width: inW, height: inH });
        $B.DomUtils.css(td, size);
        $B.DomUtils.attribute(td, { w: w, h: h, iw: inW, ih: inH });
        if (td.firstChild.style.display === "none") {
            td.firstChild.style.display = "block";
        }
    }
    /**
     * 获取行里面合并单元格
     * **/
    _getRowspanTds(targetRow) {        
        var rowEndIdx = parseInt(targetRow.id.replace("row_", ""));
        var colRec = {};
        var prevRow = targetRow.previousSibling;
        while (prevRow) {
            let childs = prevRow.children;
            for (let i = 0, len = childs.length; i < len; ++i) {
                let td = childs[i];
                let index = $B.DomUtils.attribute(td, "col");
                let rowspan = $B.DomUtils.attribute(td, "rowspan");
                if (rowspan && !colRec[index]) {
                    let rowNum = parseInt($B.DomUtils.attribute(td, "row"));
                    let rowIdx = rowNum + parseInt(rowspan) - 1;
                    if (rowEndIdx <= rowIdx) {
                        colRec[index] = td;
                    }
                }
            }
            prevRow = prevRow.previousSibling;
        }
        return colRec;
    }
    /***
     * 判定td是否在嵌套表格内
     * **/
    isInnerTable(td) {
        let ret = false;
        let $pt = td.parentNode;
        let i = 6;
        while (i >= 0 && $pt) {
            if ($pt.nodeName === "TD") {
                ret = true;
                break;
            }
            $pt = $pt.parentNode;
            i--;
        }
        return ret;
    }
    /***
     * 清除嵌套子表格的周边边框，实现融合显示
     * ***/
    clear4border(tab) {
        let trs = tab.firstChild.children;
        let len = trs.length;
        let lastRow = len - 1;
        for (let i = 0; i < len; i++) {
            let tds = trs[i].children;
            for (let j = 0; j < tds.length; j++) {
                let td = tds[j];
                let notBorder = {};
                let go = false;
                if (i === 0) {//第一行
                    notBorder["border-top"] = "none";
                    if (!td.previousSibling) {
                        notBorder["border-left"] = "none";
                    }
                    if (!td.nextSibling) {
                        notBorder["border-right"] = "none";
                    }
                    if (i === lastRow) {
                        notBorder["border-bottom"] = "none";
                    }
                    go = true;
                } else if (i === lastRow) {
                    notBorder["border-bottom"] = "none";
                    if (!td.previousSibling) {
                        notBorder["border-left"] = "none";
                    }
                    if (!td.nextSibling) {
                        notBorder["border-right"] = "none";
                    }
                    go = true;
                } else {//中间行，需要判断是否rowspan
                    let rowspan = $B.DomUtils.attr(td, "rowspan");
                    if (rowspan) {
                        rowspan = parseInt(rowspan) - 1;
                        let rowIdx = i + rowspan;
                        if (rowIdx === lastRow) {
                            otBorder["border-bottom"] = "none";
                        }
                    }
                    if (!td.previousSibling) {
                        notBorder["border-left"] = "none";
                    }
                    if (!td.nextSibling) {
                        notBorder["border-right"] = "none";
                    }
                    go = true;
                }
                if (go) {
                    $B.DomUtils.css(td, notBorder);
                }
            }
        }
    }
    /**
     * 抽取td里面嵌套的表格,可能会有多层嵌套
     * ***/
    extractSubTables(td, tabArr, fn, deep) {
        if (!deep) {
            deep = 1;
        }
        let el = td.firstChild.firstChild.firstChild.firstChild;
        if (el && el.nodeName === "TABLE") {
            tabArr.push(el);
            if (fn) {
                let _break = fn(el, deep, td);
                if (_break) {
                    return;
                }
            }
            this.foreachTd(el, (td) => {
                this.extractSubTables(td, tabArr, fn, deep + 1);
            });
        }
    }
    /**
     * 根据偏移量调整列宽
     * **/
    updateColWidthByDiff(tabEL, ofsVal, lIdx, rIdx, ctrlKey) {
        let childTable = [];
        /**
         * 通过第一层嵌套来判断嵌套子表格位于左边还是右边
         * ***/
        let subPosLeft = false; //子表格位置是否位于左边
        let onGetSubTableFn = ($table, deep, prTd) => {
            $table.style.display = "none";
            if (ctrlKey) { //按下ctrl键，会影响整个子表格
                $table.style.width = "100%";
                $table.style.height = "100%";
            }
            let go = true;
            let idx = parseInt($B.DomUtils.attr(prTd, "col"));
            if (deep === 1) {
                let colspan = $B.DomUtils.attr(prTd, "colspan");
                if (colspan) {
                    idx = idx + parseInt(colspan) - 1;
                }
                subPosLeft = lIdx === idx;
            } else {
                if (subPosLeft) {
                    go = !prTd.nextSibling;
                } else {
                    go = !prTd.previousSibling;
                }
            }
            if (go) {
                this.foreachTd($table, (td, args) => {
                    if (ctrlKey) { //按下ctrl键，会影响整个子表格
                        td.firstChild.style.display = "none";
                        td.style.height = "auto";
                    } else {
                        let w, iw;
                        if (subPosLeft) { //左侧内置表格,修改最后一列的单元格宽度
                            if (args.islastCol) {
                                w = parseFloat($B.DomUtils.attr(td, "w")) + ofsVal;
                                iw = parseFloat($B.DomUtils.attr(td, "iw")) + ofsVal;
                                td.firstChild.style.width = iw + "px";
                                td.style.width = w + "px";
                            }
                        } else {//右侧内置表格，修改第一列的单元格宽度
                            if (args.colNum === 0) {
                                w = parseFloat($B.DomUtils.attr(td, "w")) - ofsVal;
                                iw = parseFloat($B.DomUtils.attr(td, "iw")) - ofsVal;
                                td.firstChild.style.width = iw + "px";
                                td.style.width = w + "px";
                            }
                        }
                    }
                });
            }
            $table.style.display = "";
            return !go;
        };
        let trs = tabEL.firstChild.children;
        for (let i = 0; i < trs.length; i++) {
            let tds = trs[i].children;
            for (let j = 0; j < tds.length; j++) {
                let _td = tds[j];
                let idx = parseInt($B.DomUtils.attr(_td, "col"));
                if (idx > rIdx) {
                    break;
                }
                let eidx = idx;
                let colspan = $B.DomUtils.attr(_td, "colspan");
                if (colspan) {
                    eidx = idx + parseInt(colspan) - 1;
                    if (lIdx === idx && eidx >= rIdx) {
                        break;
                    }
                }
                let w, iw, sbw;
                if (lIdx === idx || eidx === lIdx) { //右侧列
                    let old = $B.DomUtils.attr(_td, "w");
                    $B.DomUtils.attr(_td, { "oldw": old });
                    w = parseFloat(old) + ofsVal;
                    iw = parseFloat($B.DomUtils.attr(_td, "iw")) + ofsVal;
                    if (_td.nextSibling) {
                        sbw = parseFloat($B.DomUtils.attr(_td.nextSibling, "w")) - ofsVal;
                    }
                } else if (rIdx === idx) {//左侧列
                    w = parseFloat($B.DomUtils.attr(_td, "w")) - ofsVal;
                    iw = parseFloat($B.DomUtils.attr(_td, "iw")) - ofsVal;
                    if (_td.previousSibling) {
                        sbw = parseFloat($B.DomUtils.attr(_td.previousSibling, "oldw")) + ofsVal;
                        $B.DomUtils.removeAttr(_td.previousSibling, "oldw");
                    }
                }
                if (w < 8 || sbw < 8) { //不合法的调整
                    return;
                }
                if (w) {
                    $B.DomUtils.attr(_td, { "w": w, "iw": iw });
                    _td.firstChild.style.width = iw + "px";
                    _td.style.width = w + "px";
                    this.extractSubTables(_td, childTable, onGetSubTableFn);
                }
            }
        }
        setTimeout(() => {
            for (let i = 0; i < childTable.length; i++) {
                let $tb = childTable[i];
                this.setWnHFromDom($tb);
            }
        }, 1);
    }
    _setRowHeightByDiff(targetRow, topofs, skipTd, ctrlKey){
        //提取行里的rowspan单元格
        let rowspanTds = this._getRowspanTds(targetRow);
        let tds = targetRow.children;
        let childTable = [];
        //提取所有子表格
        let onGetSubTableFn = ($table, deep, prTd) => {
            $table.style.display = "none";
            if (ctrlKey) { //按下ctrl键，会影响整个子表格
                $table.style.width = "100%";
                $table.style.height = "100%";
            }
            let go = true;
            if (deep !== 1) {
                go = !prTd.parentNode.nextSibling;
            }
            if (go) {
                this.foreachTd($table, (td, args) => {
                    if (ctrlKey) { //按下ctrl键，会影响整个子表格
                        td.firstChild.style.display = "none";
                        td.style.height = "auto";
                    } else {
                        if (args.isLastRow) {
                            let h = parseFloat($B.DomUtils.attr(td, "h")) + topofs;
                            let ih = parseFloat($B.DomUtils.attr(td, "ih")) + topofs;
                            $B.DomUtils.attribute(td, { "h": h, "ih": ih });
                            td.firstChild.style.height = ih + "px";
                            td.style.height = h + "px";
                        }
                    }
                });
            }
            $table.style.display = "";
            return !go;
        };
        //更新目标行
        for (let i = 0; i < tds.length; i++) {
            let td = tds[i];
            let ih = parseFloat($B.DomUtils.attribute(td, "ih"));
            let h = parseFloat($B.DomUtils.attribute(td, "h"));
            let inHeight = ih + topofs;
            let height = h + topofs;
            if (height < this.minRowHeight) {
                topofs = this.minRowHeight - h;
                inHeight = ih + topofs;
                height = h + topofs;
            }
            if (!skipTd || td !== skipTd) {
                this.extractSubTables(td, childTable, onGetSubTableFn);
            }
            $B.DomUtils.attribute(td, { "h": height, "ih": inHeight });
            td.firstChild.style.height = inHeight + "px";
            td.style.height = height + "px";
        };
        //更新跨行单元格
        Object.keys(rowspanTds).forEach((key) => {
            let td = rowspanTds[key];
            if (!skipTd || td !== skipTd) {
                this.extractSubTables(td, childTable, onGetSubTableFn);
            }
            let height = parseFloat($B.DomUtils.attribute(td, "h")) + topofs;
            let inHeight = parseFloat($B.DomUtils.attribute(td, "ih")) + topofs;
            $B.DomUtils.attribute(td, { "h": height, "ih": inHeight });
            td.firstChild.style.height = inHeight + "px";
            td.style.height = height + "px";
        });
        //更新子嵌套表格
        for (let i = 0; i < childTable.length; i++) {
            let $tb = childTable[i];
            this.setWnHFromDom($tb);
        }
        return topofs;
    }
    /**
     * 根据偏移量更新行高
     * ***/
    updateRowHeightByDiff(targetRow, topofs, skipTd, ctrlKey) {
        topofs = this._setRowHeightByDiff(targetRow, topofs, skipTd, ctrlKey);
        let goUpdatePrt = true;
        if(ctrlKey){
            //更新相邻行
            let nextRow = targetRow.nextSibling;
            if(nextRow){
                goUpdatePrt = false;
                topofs = this._setRowHeightByDiff(nextRow, -topofs, undefined, ctrlKey);
            }            
        }
        if(goUpdatePrt){
            //父级嵌套高度调整
            let $ptab = this.getTableByTr(targetRow);
            let $wap = $ptab.parentNode.parentNode.parentNode;
            if ($B.DomUtils.hasClass($wap, "k_edit_td_wap")) {
                let $skipTd = $wap.parentNode;
                let $prtTR = $skipTd.parentNode;
                this.updateRowHeightByDiff($prtTR, topofs, $skipTd);
            }
        }       
        return topofs;
    }
    bindEventsExt(el){
        if(Array.isArray(el)){
            for(let i =0 ; i < el.length ;i++){
                this.bindEvents(el[i]);
                this.clearUIStyle(el[i]);
            }
        }else{
            if(el.tagName === "TABLE"){
                this.bindEvents(el);
                this.clearUIStyle(el);
            }else{
                let arr = $B.Dom.findByTagName(el,"table");
                for(let i = 0; i < arr.length ;i++){
                    this.bindEvents(arr[i]);
                    this.clearUIStyle(arr[i]);
                }
            }
        }
    }
    clearUIStyle(table){
        let trs = table.firstChild.children;
        for(let i =0 ;i < trs.length ;i++){
            let tds = trs[i].children;
            for(let j =0 ;j < tds.length ;j++){
                let td = tds[j];
                $B.Dom.removeClass(td,"k_edit_selected_td_shadow k_edit_td_selected");
                let $wap = td.firstChild.firstChild;
                let listp = $wap.children;
                if(listp.length === 1){
                    if(listp[0].firstChild.tagName === "TABLE"){
                        this.clearUIStyle(listp[0].firstChild);
                    }
                }
            }
        }
    }
    bindEvents(tableEl) {
        if (!tableEl.hasBindEvs) {
            tableEl.hasBindEvs = true;
            if (!this.tableEvents) {
                let tdPosCached = {};
                let splitXPos,
                    splitYPos,
                    targetRow;
                let getTdFn = function (el) {
                    while (el) {
                        if (el.nodeName === "TD") {
                            break;
                        }
                        el = el.parentNode;
                    }
                    return el;
                };
                this.tableEvents = {
                    mousedown: (e) => {
                        //_skip嵌套表格防止冒泡上层表格的监听处理 
                        let ev = e._e;
                        if (!ev._skip) {
                            ev._skip = true;
                            this.clearSelected();
                            UTILS.stopDefaultctxMenu();
                            let td = getTdFn(e.target);
                            let tabEL = this.getTableByTd(td);
                            this.setTarget(tabEL);
                            this.setClickTd(td);                            
                            if ((splitXPos || splitYPos) && e.which === 1) {
                                let prtEl = this.getRootPelByTable(tabEL);
                                let splitLine;
                                let dragOpt = {
                                    nameSpace: 'dragsplit', //命名空间，一个对象可以绑定多种拖动实现
                                    which: 1, //鼠标键码，是否左键,右键 才能触发拖动，默认左右键均可                                    
                                    axis: undefined, // v垂直方 h水平，默认全向                                      
                                    onDragReady: (e) => {//鼠标按下时候准备拖动前，返回true则往下执行，返回false则停止
                                    },
                                    onStartDrag: (e) => {//开始拖动事件
                                        this.dragging = true;
                                        this.editIns.makeUndoData(prtEl);
                                    },
                                    onDrag: (e) => {//拖动中事件
                                    },
                                    onStopDrag: (p) => {//拖动结束事件
                                        tdPosCached = {};
                                        $B.DomUtils.remove(p.state.target);
                                        setTimeout(() => {
                                            this.focusTd();
                                            this.dragging = false;
                                        }, 1);
                                        let data = p.state._data;
                                        if (data.topOffset !== 0) { //行拖动
                                            console.log("drag is end updateRow ....",p,targetRow);
                                            let topofs = this.updateRowHeightByDiff(targetRow, data.topOffset, undefined, p.e.ctrlKey);
                                            if (splitYPos) {
                                                splitYPos.top = splitYPos.top + topofs;
                                            }
                                        } else if (data.leftOffset !== 0) {//列拖动
                                            //console.log("列拖动 splitXPos ", splitXPos, data.leftOffset);
                                            let ofsVal = data.leftOffset;
                                            splitXPos.left = splitXPos.left + ofsVal;
                                            let lIdx = splitXPos.leftIdx;
                                            let rIdx = splitXPos.rightIdx;
                                            this.updateColWidthByDiff(tabEL, ofsVal, lIdx, rIdx, p.e.ctrlKey);
                                        }
                                        targetRow = undefined;
                                        if(Math.abs(data.topOffset) > 5 || Math.abs(data.leftOffset) > 5){
                                            this.editIns.putUndoData(1);
                                        }else{
                                            this.editIns.clearUndoingData();
                                        }
                                    },
                                    onMouseUp: (p) => {//当没有发生拖动，鼠标放开时候调用 
                                        tdPosCached = {};
                                        targetRow = undefined;
                                        splitYPos = undefined;
                                        $B.DomUtils.remove(p.state.target);
                                        setTimeout(() => {
                                            this.focusTd();
                                            this.dragging = false;
                                            this.editIns.clearUndoingData();
                                        }, 1);
                                    }
                                };
                                if (splitXPos) {
                                    dragOpt.cursor = "w-resize";
                                    dragOpt.axis = "h";
                                    let th = $B.DomUtils.height(tabEL);
                                    let top = $B.DomUtils.offset(tabEL).top;
                                    let bHeight = $B.DomUtils.height(document.body);
                                    let diff = bHeight - (top + th);
                                    let sliptHeight = th;
                                    if (diff < 1) {
                                        sliptHeight = sliptHeight + diff;
                                    }
                                    splitLine = $B.DomUtils.createEl("<div  style='cursor:w-resize;left:" + splitXPos.left + "px;top:" + top + "px;position:absolute;height:" + sliptHeight + "px;width:2px;border-left:1px solid #FF000D;z-index:99999999999'/>");
                                } else {
                                    let tw = $B.DomUtils.width(tabEL);
                                    dragOpt.axis = "v";
                                    dragOpt.cursor = "s-resize";
                                    splitYPos["left"] = $B.DomUtils.offset(tabEL).left;
                                    splitLine = $B.DomUtils.createEl("<div style='cursor:s-resize;left:" + splitYPos.left + "px;top:" + splitYPos.top + "px;position:absolute;height:3px;width:" + tw + "px;border-top:1px solid #FF000D;z-index:99999999999'/>");
                                }
                                if (splitLine) {
                                    this.dragging = true;
                                    $B.DomUtils.append(document.body, splitLine);
                                    $B.draggable(splitLine, dragOpt);
                                    $B.DomUtils.trigger(splitLine, "dragsplit.mousedown", {
                                        pageX: e.pageX,
                                        pageY: e.pageY,
                                        which: e.which
                                    });
                                }
                            } else {
                                this.mutilSelect = true;
                            }
                            setTimeout(() => {
                                ev._skip = undefined;
                            }, 1);
                        }
                    },
                    mouseup: (e) => {
                        if (!this.dragging) {
                            let ev = e._e;
                            if (!ev._skip) {
                                ev._skip = true;
                                //let td = getTdFn(e.target);
                                //let tabEL = this.getTableByTd(td);
                                splitXPos = undefined;
                                splitYPos = undefined;
                                this.mutilSelect = false;
                                this.movingTd = undefined;
                                setTimeout(() => {
                                    ev._skip = undefined;
                                }, 1);
                            }
                            let isSelected = this.selectedTdArray.length > 0;
                            if (isSelected || e.which === 3) {
                                this.showPanel(e);
                                setTimeout(() => {
                                    let cssMap = this.extractCss();
                                    this.editIns.reactiveTools(cssMap);
                                    this.reactPanel(cssMap);
                                }, 1);
                            }
                            if (isSelected) {
                                return false; //不触发文本的选区保存
                            }
                        }
                    },
                    mousemove: (e) => {
                        if (!this.dragging) {
                            //分割线功能检测是否靠近边线
                            let ev = e._e;
                            if (!ev._skip) {
                                ev._skip = true;
                                let td = getTdFn(e.target);
                                if (td) {
                                    let tabEL = this.getTableByTd(td);
                                    splitXPos = undefined;
                                    splitYPos = undefined;
                                    if (this.tableEl === tabEL) {
                                        let tdKey = this.getTdKey(td);
                                        let tabId = tabEL.id;
                                        let tabInfo = tdPosCached[tabId];
                                        if (!tabInfo) {
                                            let info = {};
                                            tdPosCached[tabId] = info;
                                            //用于判定嵌套表格是否是左右两侧拖动
                                            let tabOfs = $B.DomUtils.offset(tabEL);
                                            let tw = $B.DomUtils.outerWidth(tabEL);
                                            let th = $B.DomUtils.outerHeight(tabEL);
                                            info["x"] = tabOfs.left + 12;
                                            info["x1"] = tabOfs.left + tw - 12;
                                            info["y"] = tabOfs.top + 12;
                                            info["y1"] = tabOfs.top + th - 12;
                                            tabInfo = info;
                                        }
                                        if (this.mutilSelect) { //划选单元格                              
                                            if (!this.movingTd) {
                                                this.movingTd = td;
                                            } else {
                                                let movingId = $B.DomUtils.attribute(this.movingTd, "row") + "_" + $B.DomUtils.attribute(this.movingTd, "col");
                                                if (movingId !== tdKey) {
                                                    this.movingTd = td;
                                                    this.makeSelectedUi();
                                                    //清除document中的选择区域
                                                    this.editIns.clearDomSelected();
                                                    return false;
                                                }
                                            }
                                        } else {//普通移动，行列拖动
                                            let info = tdPosCached[tdKey];
                                            if (!info) {//采用缓存，避免每次都触发相同的计算
                                                info = {};
                                                tdPosCached[tdKey] = info;
                                                let ofs = $B.DomUtils.offset(td);
                                                let w = $B.DomUtils.outerWidth(td);
                                                let h = $B.DomUtils.outerHeight(td);
                                                info["left"] = ofs.left;
                                                info["top"] = ofs.top;
                                                info["w"] = w;
                                                info["h"] = h;
                                            }
                                            let mouseX = e.pageX;
                                            let mouseY = e.pageY;
                                            let startXshift = mouseX - info.left;
                                            let endXshift = info.left + info.w - mouseX;
                                            this.changeCursor("text");
                                            let nearVal = this.splitNearVal;
                                            if (startXshift <= nearVal || endXshift <= nearVal) {
                                                //嵌套表格右侧，左侧不可拖动
                                                let isInner = this.isInnerTable(td);
                                                let go = true;
                                                if (isInner) {
                                                    if (mouseX < tabInfo.x || mouseX > tabInfo.x1) {
                                                        go = false;
                                                    }
                                                }
                                                if (go) {
                                                    let tdIdx = parseInt($B.DomUtils.attr(td, "col"));
                                                    if (startXshift <= nearVal) {
                                                        splitXPos = { left: info.left, leftIdx: tdIdx - 1, rightIdx: tdIdx };
                                                    } else {
                                                        let colspan = $B.Dom.attr(td, "colspan");
                                                        if (colspan) {
                                                            tdIdx = tdIdx + parseInt(colspan) - 1;
                                                        }
                                                        splitXPos = { left: info.left + info.w, leftIdx: tdIdx, rightIdx: tdIdx + 1 };
                                                    }
                                                }
                                            }
                                            if (splitXPos) {
                                                this.changeCursor("w-resize");
                                            } else { //行高拖动                   
                                                let startYshift = mouseY - info.top;
                                                let endYshift = info.top + info.h - mouseY;
                                                if (startYshift <= nearVal || endYshift <= nearVal) {
                                                    let isInner = this.isInnerTable(td);
                                                    let go = true;
                                                    if (isInner) {
                                                        if (mouseY < tabInfo.y || mouseY > tabInfo.y1) {
                                                            go = false;
                                                        }
                                                    }
                                                    if (go) {
                                                        let currentRow = td.parentNode;
                                                        if (startYshift <= nearVal) {
                                                            targetRow = currentRow.previousSibling;
                                                            splitYPos = {
                                                                "top": info.top
                                                            };
                                                        } else {
                                                            splitYPos = {
                                                                "top": info.top + info.h
                                                            };
                                                            targetRow = currentRow;
                                                        }
                                                        this.changeCursor("s-resize");
                                                    }
                                                }
                                            }
                                        }
                                        setTimeout(() => {
                                            ev._skip = undefined;
                                        }, 1);
                                    } else {
                                        this.changeTableCursor(tabEL, "text");
                                    }
                                }
                            }
                        }
                    },
                    mouseenter: (e) => {
                        tdPosCached = {};
                        if (!this.dragging) {
                            splitXPos = undefined;
                            splitYPos = undefined;
                        }
                        if (this.selectedTdArray.length === 0) {
                            let tabEL = e.target;
                            this.setTarget(tabEL);
                        }
                        return false;
                    },
                    mouseleave: (e) => {
                        tdPosCached = {};
                        if (!this.dragging) {
                            splitXPos = undefined;
                            splitYPos = undefined;
                        }
                        return false;
                    }
                };
            }
            $B.DomUtils.bind(tableEl, this.tableEvents);
        }
    }
    hidePanel() {
        if (this.$panel) {
            this.$panel.style.display = "none";
            if (!this.holdColorCtl) {
                this.colorIns.hide();
            }
        }
        this.hideSubMenu();
    }
    hideSubMenu() {
        if (this.showSubMenu) {
            this.showSubMenu.style.display = "none";
        }
    }
    showPanel(pos) {
        if (!this.$panel) {
            let opts = {
                title: editCfg.label.tableEdit,
                onClosed: ($l) => {
                    this.hideSubMenu();
                },
                onCreated: ($b) => {
                    $B.DomUtils.append($b, editCfg.tablePropsForm);
                    this.initCtxMenu($b.firstChild);
                }
            };
            this.$panel = UTILS.createCommPanel(opts);
            this.editIns.bindFocusEv(this.$panel);
        }
        if (pos.pageX && pos.pageY) {
            pos = { left: pos.pageX + 14, top: pos.pageY + 14 };
        }
        let megerTR = $B.DomUtils.findbyId(this.$panel, "_split_merge_td_");
        if (this.selectedTdArray.length > 0) { //多选了单元格           
            megerTR.style.display = "";
            megerTR.lastChild.lastChild.innerText = editCfg.label.megerTd;
            $B.DomUtils.attr(megerTR, { "fn": "megerTd" });
        } else {
            let colspan = $B.DomUtils.attr(this.clickedTd, "colspan");
            let rowspan = $B.DomUtils.attr(this.clickedTd, "rowspan");
            if (colspan || rowspan) {
                megerTR.style.display = "";
                megerTR.lastChild.lastChild.innerText = editCfg.label.splitTd;
                $B.DomUtils.attr(megerTR, { "fn": "splitTd" });
            } else {
                megerTR.style.display = "none";
            }
        }
        UTILS.showPanel(this.$panel, pos);
    }
    /**
     * 联动面板
     * ***/
    reactPanel(graphCss) {
        let cssMap = {
            "border-top": undefined,
            "border-right": undefined,
            "border-bottom": undefined,
            "border-left": undefined,
            "background-color": undefined,
            "color": undefined,
            "text-align": undefined,
            "vertical-align": undefined
        };
        var cssSpanMap = UTILS.getSpanDefcss();
        var cssPelMap = UTILS.getPelDefCss();
        $B.extendObjectFn(cssMap, cssSpanMap);
        $B.extendObjectFn(cssMap, cssPelMap);
        if (this.selectedTdArray.length > 0) {
            for (let i = 0; i < this.selectedTdArray.length; i++) {
                this.extractTdcss(this.selectedTdArray[i], cssMap);
            }
        } else {
            this.extractTdcss(this.clickedTd, cssMap);
        }
        //console.log("reactPanel", cssMap);
        //对齐联动
        cssMap["text-align"] = graphCss["text-align"];
        let halign = "h_" + cssMap["text-align"];
        let valign = "v_" + cssMap["vertical-align"];
        let halignEl, valignEl;
        let childs = this.$AlignWap.children;
        for (let i = 0; i < childs.length; i++) {
            let el = childs[i];
            $B.DomUtils.removeClass(el, "activtd");
            if ($B.DomUtils.hasClass(el, halign)) {
                halignEl = el;
            } else if ($B.DomUtils.hasClass(el, valign)) {
                valignEl = el;
            }
        }
        $B.DomUtils.addClass(halignEl, "activtd");
        $B.DomUtils.addClass(valignEl, "activtd");

        //填充色
        let bColor = cssMap["background-color"];
        $B.DomUtils.css(this.$FillColor, { "background-color": bColor });

        $B.DomUtils.css(this.$fontColor, { "background-color": cssMap["color"] });

        //边框
        let $borderEl = this.$bodyPosWap.firstChild;
        let topTrue = this.changeBorderRectUI($borderEl, cssMap, "top");
        $borderEl = $borderEl.nextSibling;
        let rightTrue = this.changeBorderRectUI($borderEl, cssMap, "right");
        $borderEl = $borderEl.nextSibling;
        let bottomTrue = this.changeBorderRectUI($borderEl, cssMap, "bottom");
        $borderEl = $borderEl.nextSibling;
        let leftTrue = this.changeBorderRectUI($borderEl, cssMap, "left");
        this.$borderSizeInput.value = "1";
        let sizeList = this.$boderSizeOpt.children;
        let styleList = this.$boderStyleOpt.children;
        if (topTrue) {
            this.changeBorderRectOps(sizeList, styleList, cssMap, "top");
        }
        if (rightTrue) {
            this.changeBorderRectOps(sizeList, styleList, cssMap, "right");
        }
        if (bottomTrue) {
            this.changeBorderRectOps(sizeList, styleList, cssMap, "bottom");
        }
        if (leftTrue) {
            this.changeBorderRectOps(sizeList, styleList, cssMap, "left");
        }

        this.$megerSplitBtn.parentNode.parentNode.style.display = "none";
        if (this.isSelectedTds()) {
            this.$megerSplitBtn.innerText = editCfg.label.megerTd;
            this.$megerSplitBtn.parentNode.parentNode.style.display = "";
        } else {
            if (this.clickedTd) {
                let rspan = $B.DomUtils.attr(this.clickedTd, "rowspan");
                let cspan = $B.DomUtils.attr(this.clickedTd, "colspan");
                if (rspan || cspan) {
                    this.$megerSplitBtn.innerText = editCfg.label.splitTd;
                    this.$megerSplitBtn.parentNode.parentNode.style.display = "";
                }
            }
        }
    }
    changeBorderRectOps(sizeList, styleList, cssMap, name) {
        let valArr = cssMap["border-" + name].split("\s+");
        $B.DomUtils.css(this.$BorderColor, { "background-color": valArr[2] });
        for (let i = 0; i < sizeList.length; i++) {
            if (sizeList[i].value === valArr[0]) {
                sizeList[i].selected = true;
            } else {
                sizeList[i].selected = false;
            }
        }
        for (let i = 0; i < styleList.length; i++) {
            if (styleList[i].value === valArr[1]) {
                styleList[i].selected = true;
                this.$borderSizeInput.value = valArr[1].replace("px", "");
            } else {
                styleList[i].selected = false;
            }
        }
    }
    changeBorderRectUI($borderEl, cssMap, name) {
        let ret = false;
        if (this.isEmptyBorder(cssMap["border-" + name])) {
            $B.DomUtils.removeClass($borderEl, "activtd");
        } else {
            $B.DomUtils.addClass($borderEl, "activtd");
            return true;
        }
    }
    isEmptyBorder(css) {
        return !css || css === "" || css === "none" || editCfg.tableNoBorder === css;
    }
    extractTdcss(td, map) {
        let plist = td.firstChild.firstChild.children;
        let border = UTILS.getBorder(td);
        this._setBorder(border, map, "top");
        this._setBorder(border, map, "right");
        this._setBorder(border, map, "bottom");
        this._setBorder(border, map, "left");
        //字体颜色
        for (let i = 0; i < plist.length; i++) {
            UTILS.loopExtractCss(plist[i], map, true);
        }
        map["background-color"] = undefined;

        //背景色
        let bgColor = $B.DomUtils.css(td, "background-color");
        UTILS.setCssMapVal(map, { "background-color": bgColor }, "background-color");

        map["vertical-align"] = undefined;
        map["text-align"] = undefined;
        //对齐
        let vertical = $B.DomUtils.css(td, "vertical-align");
        UTILS.setCssMapVal(map, { "vertical-align": vertical }, "vertical-align");
        let textAlign = $B.DomUtils.css(td, "text-align");
        UTILS.setCssMapVal(map, { "text-align": textAlign }, "text-align");

    }
    _setBorder(border, map, key) {
        let name = "border-" + key;
        if (map[name] === undefined) {
            map[name] = border[name];
        } else if (map[name] !== null && map[name] !== border[name]) {
            map[name] = null;
        }
    }
    extractCss() {
        let cssSpanMap = UTILS.getSpanDefcss();
        let cssPelMap = UTILS.getPelDefCss();
        if (this.cssPelist.length > 0) {
            this.forPels(($p) => {
                UTILS.extractPcss($p, cssPelMap);
                let childs = $p.children;
                for (let i = 0; i < childs.length; i++) {
                    let $s = childs[i];
                    if ($s.nodeName === "SPAN") {
                        UTILS.extractSpancss($s, cssSpanMap);
                    }
                }
            });
        } else {
            this.foreachTdInnerPls(($p, $s, td) => {
                UTILS.extractPcss($p, cssPelMap);
                let childs = $p.children;
                for (let i = 0; i < childs.length; i++) {
                    let $s = childs[i];
                    if ($s.nodeName === "SPAN") {
                        UTILS.extractSpancss($s, cssSpanMap);
                    }
                }
            }, true);
        }
        let cssMap = $B.extendObjectFn(cssSpanMap, cssPelMap);
        return cssMap;
    }
    initCtxMenu($f) {
        let $wap = $B.DomUtils.findbyId($f, "_border_size_input");
        let $input = $B.DomUtils.createEl("<p style='padding:0px 0px;'><input style='width:58px;' type='text'/></p>");
        $B.createTextIfr($wap, $input);
        $input = $input.firstChild;//边框输入
        this.$borderSizeInput = $input;
        //修饰目标
        let $tg = $B.DomUtils.findbyId($f, "_target_table_1");
        this.css2TargetRadio = $tg;
        //边框位置
        let $bwap = $B.DomUtils.findbyId($f, "k_edit_border_wrap");
        this.$bodyPosWap = $bwap;
        $B.DomUtils.click($bwap, (e) => {
            if ($B.DomUtils.hasClass(e.target, "_border_it")) {
                if ($B.DomUtils.hasClass(e.target, "activtd")) {
                    $B.DomUtils.removeClass(e.target, "activtd");
                } else {
                    $B.DomUtils.addClass(e.target, "activtd");
                }
                this.borderFn();
            }
        });
        //边框大小
        $B.DomUtils.input($input, (e) => {
            this.borderFn();
        });
        let $sizeOPts = $B.DomUtils.findbyId($f, "_border_size_opts_");
        this.$boderSizeOpt = $sizeOPts;
        $B.DomUtils.change($sizeOPts, (e) => {
            $input.value = e.target.value.replace("px", "");
            setTimeout(() => { this.borderFn(); }, 1);
        });
        //边框类型
        let $bstye = $B.DomUtils.findbyId($f, "_border_style_opts_");
        this.$boderStyleOpt = $bstye;
        $B.DomUtils.change($bstye, (e) => {
            setTimeout(() => { this.borderFn(); }, 1);
        });
        //边框颜色
        let $bcolor = $B.DomUtils.findbyId($f, "_border_color_picker");
        this.$BorderColor = $bcolor;
        $B.DomUtils.click($bcolor, (e) => {
            let el = e.target;
            if (el.nodeName === "I") {
                el = el.parentNode;
            }
            if(this.colorIns.isShow() &&  el === this.colorIns.target){
                this.colorIns.hide();
            }else{
                let bgColor = $B.DomUtils.css(el, "background-color");
                this.colorIns._callFnKey = "tableColor";
                this.colorIns.setValue(bgColor, 1);
                this.colorIns.show(el);
                this.$colorEL = el;
                this.colorCaller = "borderFn";
            }
            return false;
        });

        //字体颜色 _font_color_picker _fill_color_picker
        let $fcolor = $B.DomUtils.findbyId($f, "_font_color_picker");
        this.$fontColor = $fcolor;
        $B.DomUtils.click($fcolor, (e) => {
            let el = e.target;
            if (el.nodeName === "I") {
                el = el.parentNode;
            }
            if(this.colorIns.isShow() &&  el === this.colorIns.target){
                this.colorIns.hide();
            }else{
                let bgColor = $B.DomUtils.css(el, "background-color");
                this.colorIns._callFnKey = "tableColor";
                this.colorIns.setValue(bgColor, 1);
                this.colorIns.show(el);
                this.$colorEL = el;
                this.colorCaller = "fontColorFn";
            }            
            return false;
        });

        //填充颜色
        let $fillcolor = $B.DomUtils.findbyId($f, "_fill_color_picker");
        this.$FillColor = $fillcolor;
        $B.DomUtils.click($fillcolor, (e) => {
            let el = e.target;
            if (el.nodeName === "I") {
                el = el.parentNode;
            }
            if(this.colorIns.isShow() &&  el === this.colorIns.target ){
                this.colorIns.hide();
            }else{
                let bgColor = $B.DomUtils.css(el, "background-color");
                this.colorIns._callFnKey = "tableColor";
                this.colorIns.setValue(bgColor, 1);
                this.colorIns.show(el);
                this.$colorEL = el;
                this.colorCaller = "backgroundColorFn";
            }
            return false;
        });

        //对齐
        let $align = $B.DomUtils.findbyId($f, "_table_align");
        $B.DomUtils.click($align, (e) => {
            let el = e.target;
            let clz = "_h";
            if (el.nodeName === "I") {
                el = el.parentNode;
            }
            if ($B.DomUtils.hasClass(el, "_v")) {
                clz = "_v";
            }
            let prevs = el.previousSibling;
            let nexts = el.nextSibling;
            while (prevs) {
                if ($B.DomUtils.hasClass(prevs, clz)) {
                    $B.DomUtils.removeClass(prevs, "activtd");
                }
                prevs = prevs.previousSibling;
            }
            while (nexts) {
                if ($B.DomUtils.hasClass(nexts, clz)) {
                    $B.DomUtils.removeClass(nexts, "activtd");
                }
                nexts = nexts.nextSibling;
            }
            if (el.nodeName === "DIV") {
                if ($B.DomUtils.hasClass(el, "activtd")) {
                    $B.DomUtils.removeClass(el, "activtd");
                } else {
                    $B.DomUtils.addClass(el, "activtd");
                }
            }
            if (clz === "_h") {
                if ($B.Dom.hasClass(el, "h_center")) {
                    let btn = this.editIns.toolIns ? this.editIns.toolIns.btnElMap["alignCenterFn"] : undefined;
                    this.alignCenterFn(undefined, btn);
                } else if ($B.Dom.hasClass(el, "h_right")) {
                    let btn = this.editIns.toolIns ? this.editIns.toolIns.btnElMap["alignRightFn"] : undefined;
                    this.alignRightFn(undefined, btn);
                } else if ($B.Dom.hasClass(el, "h_left")) {
                    let btn = this.editIns.toolIns ? this.editIns.toolIns.btnElMap["alignLeftFn"] : undefined;
                    this.alignLeftFn(undefined, btn);
                }
            } else {
                if ($B.Dom.hasClass(el, "v_top")) {
                    this.vAlignTop();
                } else if ($B.Dom.hasClass(el, "v_middle")) {
                    this.vAlignMiddel();
                } else if ($B.Dom.hasClass(el, "v_bottom")) {
                    this.vAlignBottom();
                }
            }
        });
        this.$AlignWap = $align;

        //插入,删除
        let $insertNode = $B.DomUtils.findbyId($f, "_insert_op_tr");
        let $deleteNode = $B.DomUtils.findbyId($f, "_delete_op_tr");
        let events = {
            mouseenter: (e) => {
                let el = e.target;
                let id = el.id;
                if (!this[id]) {
                    this[id] = UTILS.createChildCtxMenu(id, editCfg.tableCtx[id], (fn, params) => {                      
                        if (typeof this[fn] === "function") {
                            this[fn](params);
                        } else {
                            console.log(fn + " is not found!");
                        }
                    });
                }
                if (this.showSubMenu && this.showSubMenu !== this[id]) {
                    this.hideSubMenu();
                }
                UTILS.showCtxMenu(this[id], el);
                this.showSubMenu = this[id];
            }
        };
        $B.DomUtils.bind($insertNode, events);
        $B.DomUtils.bind($deleteNode, events);

        let hideFn = (e) => {
            this.hideSubMenu();
        };
        $B.DomUtils.mouseenter($insertNode.previousSibling, hideFn);
        $B.DomUtils.mouseenter($deleteNode.nextSibling, hideFn);

        //段落设置
        let $graph = $deleteNode.nextSibling;
        $B.Dom.click($graph, (e) => {
            //console.log("open graph........................",this.$panel.lastChild.lastChild);
            this.$panel.lastChild.lastChild.openFlag = 'table';;
            let $fb = this.editIns.toolIns.paragraphFnMaker("paragraphFn", this.$panel.lastChild.lastChild);
            this.hidePanel();
            let cssMap = this.extractCss();
            this.editIns.toolIns.rectiveGraphUI($fb, cssMap);
        });
        //拆分合并
        $B.DomUtils.click($graph.nextSibling, (e) => {
            let el = e.target;
            if (el.nodeName === "TR") {
                el = el.firstChild.lastChild;
            } else {
                while (el) {
                    if (el.nodeName === "TD") {
                        break;
                    }
                    el = el.parentNode;
                }
                el = el.lastChild;
            }
            let lable = el.innerText;
            if (lable === editCfg.label.megerTd) {
                this.megerTd();
            } else {
                this.splitTd();
            }
            this.hidePanel();
        });
        this.$megerSplitBtn = $graph.nextSibling.lastChild.lastChild;
    }
    borderFn() {
        let borderCss = {};
        let childs = this.$bodyPosWap.children;
        for (let i = 0; i < childs.length; i++) {
            if ($B.DomUtils.hasClass(childs[i], "activtd")) {
                borderCss[$B.DomUtils.attr(childs[i], "tg")] = undefined;
            }
        }
        let size = this.$borderSizeInput.value;
        if (size === "") {
            size = this.$boderSizeOpt.value;
        } else {
            size = size + "px";
        }
        let style = this.$boderStyleOpt.value;
        let color = $B.DomUtils.css(this.$BorderColor, "background-color");
        let keys = Object.keys(borderCss);
        for (let i = 0; i < keys.length; i++) {
            borderCss[keys[i]] = size + " " + style + " " + color;
        }
        let isTable = $B.DomUtils.attr(this.css2TargetRadio, "checked");
        if (isTable) { //表格修饰
            let rowNum = parseInt($B.DomUtils.attr(this.tableEl, "row")) - 1;
            this.foreachTd(this.tableEl, (td, args) => {
                let newCss = {};
                let go = false;
                if (!td.previousSibling) {
                    if (borderCss["border-left"]) {
                        newCss["border-left"] = borderCss["border-left"];
                        go = true;
                    } else {
                        this.removeTdSomeBorder(td, "left");
                    }
                }
                if (!td.nextSibling) {
                    if (borderCss["border-right"]) {
                        newCss["border-right"] = borderCss["border-right"];
                        go = true;
                    } else {
                        this.removeTdSomeBorder(td, "right");
                    }
                }
                if (args.rowNum === 0) {
                    if (borderCss["border-top"]) {
                        newCss["border-top"] = borderCss["border-top"];
                        go = true;
                    } else {
                        this.removeTdSomeBorder(td, "top");
                    }
                }
                let rowspan = $B.DomUtils.attr(td, "rowspan");
                if (rowspan) {
                    let endRow = args.rowNum + parseInt(rowspan) - 1;
                    rowspan = endRow === rowNum;
                }
                if (args.rowNum === rowNum || rowspan) {
                    if (borderCss["border-bottom"]) {
                        newCss["border-bottom"] = borderCss["border-bottom"];
                        go = true;
                    } else {
                        this.removeTdSomeBorder(td, "bottom");
                    }
                }
                if (go) {
                    console.log(td, newCss);
                    this.updateTdBorder(td, newCss);
                }
            });
        } else {
            if (this.isSelectedTds()) {
                for (let i = 0; i < this.selectedTdArray.length; ++i) {
                    let td = this.selectedTdArray[i];
                    this.updateTdBorder(td, borderCss);
                    this.css2Siblings(td);
                }
            } else {
                this.updateTdBorder(this.clickedTd, borderCss);
                this.css2Siblings(this.clickedTd);
            }
        }
    }
    updateTdBorder(td, borderCss) {
        let cssObj = this.getNotBorderStyle(td);
        $B.extendObjectFn(cssObj, borderCss);
        let style = $B.cssObj2string(cssObj);
        $B.DomUtils.attr(td, { style: style });
    }
    getNotBorderStyle(td) {
        let cssObj = $B.style2cssObj(td);
        let keys = Object.keys(cssObj);
        for (let i = 0; i < keys.length; ++i) {
            let key = keys[i];
            if (key.indexOf("border") > -1) {
                delete cssObj[key];
            }
        }
        return cssObj;
    }
    css2Siblings(td) {
        var prevTd = td.previousSibling;
        var nextTd = td.nextSibling;
        var idx = parseInt($B.Dom.attr(td,"col"));
        if(prevTd){
            let prevIdx =  parseInt($B.Dom.attr(prevTd,"col")) + 1;
            if(prevIdx !== idx){
                prevTd = undefined;
            }
        }
        if(nextTd){
            let nextIdx =  parseInt($B.Dom.attr(nextTd,"col")) - 1;
            if(nextIdx !== idx){
                nextTd = undefined;
            }
        }
        var row = td.parentNode;
        var prevRow = row.previousSibling;
        var nextRow = row.nextSibling;
        var bodyObj = UTILS.getBorder(td);
        var borderTop = bodyObj["border-top"];
        var borderRight = bodyObj["border-right"];
        var borderBottom = bodyObj["border-bottom"];
        var borderLeft = bodyObj["border-left"];
        if (this.isEmptyBorder(borderTop)) {
            borderTop = undefined;
        }
        if (this.isEmptyBorder(borderRight)) {
            borderRight = undefined;
        }
        if (this.isEmptyBorder(borderBottom)) {
            borderBottom = undefined;
        }
        if (this.isEmptyBorder(borderLeft)) {
            borderLeft = undefined;
        }
        if (nextTd) {
            if (borderRight) {
                $B.DomUtils.css(nextTd, { "border-left": borderRight });
            } else {
                this.removeTdSomeBorder(nextTd, "left");
            }
        }
        if (prevTd) {
            if (borderLeft) {
                $B.DomUtils.css(prevTd, { "border-right": borderLeft });
            } else {
                this.removeTdSomeBorder(prevTd, "right");
            }
        }
        var index = parseInt($B.DomUtils.attr(td, "col"));
        if (prevRow) {
            let tds = prevRow.children
            for (let i = 0; i < tds.length; i++) {
                let _td = tds[i];
                let colspan = $B.DomUtils.attr(_td, "colspan");
                let idx = parseInt($B.DomUtils.attr(_td, "col"));
                if (!colspan) {
                    if (index === idx) {
                        if (borderTop) {
                            $B.DomUtils.css(_td, { "border-bottom": borderTop });
                        } else {
                            this.removeTdSomeBorder(_td, "bottom");
                        }
                        break;
                    }
                }
                if (idx > index) {
                    break;
                }
            }
        }
        if (nextRow && borderBottom) {
            let tds = nextRow.children
            for (let i = 0; i < tds.length; i++) {
                let _td = tds[i];
                let colspan = $B.DomUtils.attr(_td, "colspan");
                let idx = parseInt($B.DomUtils.attr(_td, "col"));
                if (!colspan) {
                    if (index === idx) {
                        if (borderBottom) {
                            $B.DomUtils.css(_td, { "border-top": borderBottom });
                        } else {
                            this.removeTdSomeBorder(_td, "top");
                        }
                        break;
                    }
                }
                if (idx > index) {
                    break;
                }
            }
        }
    }
    removeTdSomeBorder(_td, delBorder) {
        let borderObj = UTILS.getBorder(_td, delBorder);
        let cssObj = this.getNotBorderStyle(_td);
        $B.extendObjectFn(cssObj, borderObj);
        let style = $B.cssObj2string(cssObj);
        $B.DomUtils.attr(_td, { style: style });
    }
    makeUndoRec(el){
        let $p;
        if(el.tagName === "TABLE"){
            $p = this.getRootPelByTable(el);
        }else{
            $p = this.getRootPelByTd(el);
        }        
        this.editIns.makeUndoData($p);
        this.editIns.putUndoData(1);
    }
    splitTd() {
        this.makeUndoRec(this.clickedTd);
        let colspan = parseInt($B.Dom.attr(this.clickedTd, "colspan"));
        let rowCount = parseInt($B.Dom.attr(this.clickedTd, "rowspan")) - 1;
        let col = parseInt($B.Dom.attr(this.clickedTd, "col"));
        let row = parseInt($B.Dom.attr(this.clickedTd, "row"));
        let tdWidth = parseFloat($B.Dom.attr(this.clickedTd, "w"));
        let td;
        let copyStyle = $B.style2cssObj(this.clickedTd);
        delete copyStyle.width;
        delete copyStyle.height;
        let avgWidth;
        let isNolyRow = this.tableEl.firstChild.children.length === 1;
        if (colspan) {
            colspan = parseInt(colspan);
            avgWidth = tdWidth / colspan;
            if (isNolyRow) {
                copyStyle.width = avgWidth + "px";
            }
            this.clickedTd.style.width = avgWidth + "px";
            this.clickedTd.firstChild.style.width = "auto";
            $B.Dom.removeAttr(this.clickedTd, "colspan");
            let count = colspan - 1;
            let curCol = col;
            let insertTarget = this.clickedTd;
            while (count > 0) {
                curCol = curCol + 1;
                td = Table.createTD({
                    "tabindex": "0",
                    "row": row,
                    "col": curCol
                }, copyStyle);
                count = --count;
                $B.Dom.after(insertTarget, td);
                insertTarget = td;
            }
        }
        if (rowCount) {
            let tdCount = 1; //需要创建的td数量
            if (colspan) {
                tdCount = colspan;
            }
            if (!avgWidth) {
                avgWidth = tdWidth;
                if (isNolyRow) {
                    copyStyle.width = avgWidth + "px";
                }
            }
            this.clickedTd.style.width = avgWidth + "px";
            this.clickedTd.style.height = "auto";
            this.clickedTd.firstChild.style.height = "auto";
            $B.Dom.removeAttr(this.clickedTd, "rowspan");
            let tdRow = this.clickedTd.parentNode;
            let currentRow = tdRow.nextSibling;
            let curRow = row;
            while (rowCount > 0) {
                curRow = curRow + 1;
                if (!currentRow) {
                    currentRow = Table.createTR({
                        "id": "row_" + curRow
                    });
                    $B.Dom.append(this.tableEl.firstChild, currentRow);
                }
                let targetTd, index, helper, count, colIdx;
                let childArray = currentRow.children;
                let len = childArray.length;
                if (len === 0) {
                    len = 1;
                }
                for (let i = 0; i < len; ++i) {
                    targetTd = undefined;
                    if (childArray.length === 0) {
                        targetTd = 1;
                    } else {
                        td = childArray[i];
                        index = parseInt($B.Dom.attr(td, "col"));
                        if (index >= col) {
                            if (td.previousSibling) {
                                targetTd = td.previousSibling;
                            } else {
                                targetTd = 1;
                            }
                        } else if (!td.nextSibling) {
                            targetTd = td;
                        }
                    }
                    if (targetTd) {
                        helper = 0;
                        count = tdCount;
                        if (targetTd === 1) {
                            colIdx = -1;
                        } else {
                            colIdx = parseInt($B.Dom.attr(targetTd, "col"));
                        }
                        while (count > 0) {
                            colIdx++;
                            td = Table.createTD({
                                "tabindex": "0",
                                "row": curRow,
                                "col": colIdx
                            }, copyStyle);
                            td.style.width = avgWidth + "px";
                            td.style.height = "auto";
                            if (targetTd === 1) {
                                $B.Dom.prepend(currentRow, td);
                            } else {
                                $B.Dom.after(targetTd, td);
                            }
                            targetTd = td;
                            count = --count;
                        }
                        break;
                    }
                }
                currentRow = currentRow.nextSibling;
                rowCount = --rowCount;
            }
        }
        this.setWnHFromDom(this.tableEl);
    }
    megerTd() {
        console.log("megerTd go.........");
        let rowspan = 0,
            colspan = 0,
            modifyTd, //需要合并到的单元格
            rowSet = new Set(), //合并的行号
            colSet = new Set(); //合并的列号
        this.foreachSeletedTds(function (td) {
            let row = parseInt($B.DomUtils.attr(td, "row"));
            let col = parseInt($B.DomUtils.attr(td, "col"));
            //找到待合并的单元格
            if (!modifyTd) {
                modifyTd = td;
            } else {
                let r = parseInt($B.DomUtils.attr(modifyTd, "row"));
                if (row < r) {
                    modifyTd = td;
                } else if (r === row) {
                    let l = parseInt($B.DomUtils.attr(modifyTd, "col"));
                    if (col < l) {
                        modifyTd = td;
                    }
                }
            }
            //被合并的行号
            rowSet.add(row);
            rowspan = $B.DomUtils.attr(td, "rowspan");
            if (rowspan) {
                rowspan = parseInt(rowspan) - 1;
                let r = row;
                while (rowspan > 0) {
                    r++;
                    rowSet.add(r);
                    rowspan--;
                }
            }
            colSet.add(col);
            colspan = $B.DomUtils.attr(td, "colspan");
            if (colspan) {
                colspan = parseInt(colspan) - 1;
                let r = col;
                while (colspan > 0) {
                    r++;
                    colSet.add(r);
                    colspan--;
                }
            }
        });
        if (modifyTd) {
            this.makeUndoRec(modifyTd);
            rowspan = rowSet.size;
            colspan = colSet.size;
            let rowMap = {};
            let rHMap = {};
            let tabWidth = $B.Dom.width(this.tableEl.firstChild);
            let megerColMap = {};
            let megerColWidthMap = {};
            let rmTdArr = [];
            this.foreachSeletedTds(function (td) {
                if (td !== modifyTd) {
                    let rowspan = $B.Dom.attr(td, "rowspan");
                    let l = $B.Dom.attr(td, "col");
                    let r = $B.Dom.attr(td, "row");
                    if (megerColMap[l]) {
                        if (rowspan) {
                            megerColMap[l] = megerColMap[l] + parseInt(rowspan);
                        } else {
                            megerColMap[l] = megerColMap[l] + 1;
                        }
                    } else {
                        if (rowspan) {
                            megerColMap[l] = parseInt(rowspan);
                        } else {
                            megerColMap[l] = 1;
                        }
                    }
                    if (!rowMap[r]) {
                        rowMap[r] = td.parentNode;
                        let h = $B.Dom.height(td.parentNode);
                        rHMap[r] = h;
                    }
                    let tmpW = $B.Dom.width(td);
                    if (megerColWidthMap[l]) {
                        if (megerColWidthMap[l] > tmpW) {
                            megerColWidthMap[l] = tmpW;
                        }
                    } else {
                        megerColWidthMap[l] = tmpW;
                    }
                    rmTdArr.push(td);
                }
            });
            for (let i = 0; i < rmTdArr.length; i++) {
                $B.Dom.remove(rmTdArr[i]);
            }
            let allHeight = $B.Dom.height(modifyTd.parentNode);
            Object.keys(rowMap).forEach((key) => {
                let tr = rowMap[key];
                if (tr.children.length === 0) {
                    tr.parentNode.removeChild(tr);
                    allHeight = allHeight + rHMap[key];
                }
            });
            if (rowspan > 1 || colspan > 1) {
                let newAttr = {};
                if (rowspan > 1) {
                    newAttr["rowspan"] = rowspan;
                }
                if (colspan > 1) {
                    newAttr["colspan"] = colspan;
                }
                $B.Dom.attr(modifyTd, newAttr);
                //先判断是否是全表合并
                let $tboy = this.tableEl.firstChild;
                if ($tboy.children.length === 1 && $tboy.children[0].children.length === 1) {
                    modifyTd.style.width = tabWidth + "px";
                    modifyTd.style.height = allHeight + "px";
                } else {
                    let rowNum = parseInt($B.Dom.attr(this.tableEl, "row"));
                    //是否是整列删除
                    let diffWidth = 0;
                    Object.keys(megerColMap).forEach((key) => {
                        if (megerColMap[key] === rowNum) {
                            diffWidth = diffWidth + megerColWidthMap[key];
                        }
                    });
                    if (diffWidth > 0) {
                        let tdWidth = $B.Dom.width(modifyTd);
                        modifyTd.style.width = tdWidth + diffWidth + "px";
                    }
                }
                this._updateTdSizeFromDom(modifyTd);
            }
            this.hidePanel();
            this.clearSelected();
            this.setClickTd(modifyTd);
        }
    }
    insertRight() {
        this.insertColFn("r");
    }
    insertLeft() {
        this.insertColFn("l");
    }
    /**
     * l左侧插入列  
     * r右侧插入列
     * **/
    insertColFn(prs) {
        this.hidePanel();
        //console.log("insertColFn insertColFn insertColFn-----> ", prs);
        this.makeUndoRec(this.clickedTd);
        let col = parseInt($B.Dom.attr(this.clickedTd, "col"));
        let endCol = col;
        let sp = $B.Dom.attr(this.clickedTd, "colspan");
        if (sp) {
            endCol = col + parseInt(sp) - 1;
        }
        let trs = this.tableEl.firstChild.children;
        let colSubTableCouter = {};
        for (let i = 0; i < trs.length; i++) {
            let tr = trs[i];
            let tds = tr.children;
            for (let j = 0; j < tds.length; j++) {
                let td = tds[j];
                let col = $B.Dom.attr(td, "col");
                let colspan = $B.Dom.attr(td, "colspan");
                let tableCOUnt = 0;
                if (td.firstChild.firstChild.firstChild.firstChild.tagName === "TABLE") {
                    tableCOUnt = 1;
                }
                if (colspan) {
                    let endCol = parseInt(col) + parseInt(colspan) - 1;
                    if (!colSubTableCouter[endCol]) {
                        colSubTableCouter[endCol] = tableCOUnt;
                    }
                }
                if (!colSubTableCouter[col]) {
                    colSubTableCouter[col] = tableCOUnt;
                }
            }
        }
        let newCol, need2fixLastTd;
        if (prs === "l") {
            newCol = col;
        } else {
            newCol = col + 1;
            if (endCol === col && !this.clickedTd.nextSibling) {
                need2fixLastTd = true;
            }
        }
        for (let i = 0; i < trs.length; i++) {
            let tr = trs[i];
            let tds = tr.children;
            for (let j = 0; j < tds.length; j++) {
                let td = tds[j];
                let style = $B.style2cssObj(td); // $B.Dom.attr(td,"style") ;
                let idx = parseInt($B.Dom.attr(td, "col"));
                let row = parseInt($B.Dom.attr(td, "row"));
                let endIdx = idx;
                let colspan = $B.Dom.attr(td, "colspan");
                if (colspan) {
                    endIdx = idx + parseInt(colspan) - 1;
                }
                if (prs === "l") { //左侧插入
                    if (newCol === 0) {
                        this.insertingMakeTd(prs, td, colSubTableCouter, row, newCol, style, "before");
                        break;
                    }
                    if (idx === col) {
                        this.insertingMakeTd(prs, td, colSubTableCouter, row, newCol, style, "before");
                        break;
                    }
                    if (colspan && col >= idx && col <= endIdx) {
                        $B.Dom.attr(td, { "colspan": parseInt(colspan) + 1 });
                        this.colIndxAdd1(td.nextSibling);
                        break;
                    }
                    if (idx > col) {
                        if ((idx - 1) === newCol) {
                            this.insertingMakeTd(prs, td, colSubTableCouter, row, newCol, style, "before");
                            break;
                        }
                        if (td.previousSibling) {
                            let prevTd = td.previousSibling;
                            let prevIdx = parseInt($B.Dom.attr(prevTd, "col"));
                            let span = $B.Dom.attr(prevTd, "colspan");
                            if (span) {
                                prevIdx = prevIdx + parseInt(span) - 1;
                            }
                            if ((prevIdx + 1) === newCol) {
                                this.insertingMakeTd(prs, prevTd, colSubTableCouter, row, newCol, style, "after");
                                break;
                            }
                        }
                        this.colIndxAdd1(td);
                        break;
                    }
                    if (idx < col && !td.nextSibling) {
                        let tmp = col - 1;
                        if (endIdx === tmp) {
                            this.insertingMakeTd(prs, td, colSubTableCouter, row, newCol, style, "after");
                            break;
                        }
                    }
                } else { //右边插入
                    if (endIdx === col) {
                        this.insertingMakeTd(prs, td, colSubTableCouter, row, newCol, style, "after");
                        break;
                    }
                    if (colspan && idx <= col && endIdx >= col) {
                        this.updateColSpan(colspan, td);
                        break;
                    }
                    if (idx > col) {
                        if (newCol === idx) {
                            this.insertingMakeTd(prs, td, colSubTableCouter, row, newCol, style, "before");
                            break;
                        }
                        this.colIndxAdd1(td);
                        break;
                    }
                    if (idx < col) {
                        if (!td.nextSibling && need2fixLastTd) {
                            this.insertingMakeTd(prs, td, colSubTableCouter, row, newCol, style, "after");
                            break;
                        }
                    }

                }
            }
        }
        this.setWnHFromDom(this.tableEl);
        let colNum = parseInt($B.Dom.attr(this.tableEl, "col")) + 1;
        $B.Dom.attr(this.tableEl, { "col": colNum });
    }
    insertingMakeTd(prs, targetId, colSubTableCouter, row, newCol, style, actionName) {
        let colWidth = this.modifySibligTdWidth(prs, targetId, colSubTableCouter);
        if (colWidth === 0) {
            colWidth = 66; //撑开整个表格
        }
        style.width = colWidth + "px";
        style.height = "auto";
        let newTd = Table.createTD({
            row: row,
            col: newCol
        }, style);
        $B.Dom[actionName](targetId, newTd);
        this.colIndxAdd1(newTd.nextSibling);
    }
    colIndxAdd1(td) {
        while (td) {
            let nCol = parseInt($B.Dom.attr(td, "col")) + 1;
            $B.Dom.attr(td, { "col": nCol });
           // td.firstChild.firstChild.firstChild.firstChild.innerText = nCol;
            td = td.nextSibling;
        }
    }
    updateColSpan(colspan, td) {
        colspan = parseInt(colspan) + 1;
        $B.Dom.attr(td, { colspan: colspan });
        let nextTd = td.nextSibling;
        if (nextTd) {
            this.colIndxAdd1(nextTd);
        }
    }
    /**
     * 如果该列对应的单元格存在嵌套表格，则不做出让
     * **/
    modifySibligTdWidth(flag, td, counter) {
        let avliWidth = 0;
        //列宽大于40才能出让
        let preEl = flag === "l" ? td.previousSibling : td;
        let nextEl = flag === "l" ? td : td.nextSibling;
        while (preEl) {
            let col = $B.Dom.attr(preEl, "col");
            if (counter[col] === 0) {
                let w = parseFloat($B.Dom.attr(preEl, "w"));
                if (w > 40) {
                    if (nextEl) {
                        avliWidth = w / 4;
                        w = w - avliWidth;
                    } else {
                        avliWidth = w / 2;
                        w = avliWidth;
                    }
                    preEl.firstChild.style.width = (w - 1) + "px";
                    preEl.style.width = w + "px";
                    break;
                }
            }
            preEl = preEl.previousSibling;
        }
        while (nextEl) {
            let col = $B.Dom.attr(nextEl, "col");
            if (counter[col] === 0) {
                let w = parseFloat($B.Dom.attr(nextEl, "w"));
                if (w > 40) {
                    let haftw;
                    if (avliWidth > 0) {
                        haftw = w / 4;
                        w = w - haftw;
                    } else {
                        haftw = w / 2;
                        w = haftw;
                    }
                    nextEl.firstChild.style.width = (w - 1) + "px";
                    nextEl.style.width = w + "px";
                    avliWidth = avliWidth + haftw;
                    break;
                }
            }
            nextEl = nextEl.nextSibling;
        }
        return avliWidth;
    }
    insertUp() {
        this.insertRowFn("t");
    }
    insertDown() {
        this.insertRowFn("d");
    }
    insertRowFn(prs) {
        this.hidePanel();
        this.makeUndoRec(this.clickedTd);
        var currentRow = this.clickedTd.parentNode;
        var rowIdx = parseInt($B.Dom.attr(this.clickedTd, "row"));
        var newTr = Table.createTR();
        var newTd;
        if (prs === "t") { //上方插入
            $B.Dom.attr(newTr, { "id": "row_" + rowIdx });
            $B.Dom.before(currentRow, newTr);
        } else {
            let rowspan = $B.Dom.attr(this.clickedTd, "rowspan");
            if (rowspan) {
                rowspan = parseInt(rowspan) - 1;
                while (rowspan > 0) {
                    currentRow = currentRow.nextSibling;
                    rowspan--;
                }
                rowIdx = parseInt($B.Dom.attr(currentRow, "id").replace("row_", ""));
            }
            rowIdx++;
            $B.Dom.attr(newTr, { "id": "row_" + rowIdx });
            $B.Dom.after(currentRow, newTr);
        }
        var currentRowIndex = rowIdx;
        /***更新后面的id行号***/
        var nextRow = newTr.nextSibling;
        while (nextRow) {
            rowIdx++;
            $B.Dom.attr(nextRow, { "id": "row_" + rowIdx });
            let childs = nextRow.children;
            for (let i = 0; i < childs.length; i++) {
                $B.Dom.attr(childs[i], { "row": rowIdx });
            }
            nextRow = nextRow.nextSibling;
        }
        //分析需要插入多少个td,提前需要rowspan+1的单元格
        var prevRow = newTr.previousSibling;
        var rowspanTds = [];
        var notCreateTd = {};
        var td, rspan;
        while (prevRow) {
            let ridx = parseInt($B.Dom.attr(prevRow, "id").replace("row_", ""));
            let childs = prevRow.children;
            for (let i = 0, len = childs.length; i < len; ++i) {
                td = childs[i];
                let tdIdx = parseInt($B.Dom.attr(td, "col"));
                if (!notCreateTd[tdIdx]) {
                    rspan = $B.Dom.attr(td, "rowspan");
                    if (rspan) {
                        rspan = parseInt(rspan) - 1;
                        let tmp = ridx + rspan;
                        if (tmp >= currentRowIndex) {
                            notCreateTd[tdIdx] = true;
                            let colspan = $B.Dom.attr(td, "colspan");
                            if (colspan) {
                                colspan = parseInt(colspan) - 1;
                                while (colspan > 0) {
                                    tdIdx++;
                                    notCreateTd[tdIdx] = true;
                                    colspan--;
                                }
                            }
                            rowspanTds.push(td);
                        }
                    }
                }
            }
            prevRow = prevRow.previousSibling;
        }
        var colNum = parseInt($B.Dom.attr(this.tableEl, "col"));
        var colIdx = 0;
        let cssObj = $B.style2cssObj(this.clickedTd);
        cssObj.height = "auto";
        cssObj.width = "auto";
        while (colIdx < colNum) {
            if (!notCreateTd[colIdx]) {
                newTd = Table.createTD({
                    "tabindex": "0",
                    "row": currentRowIndex,
                    "col": colIdx
                }, cssObj);
                $B.Dom.append(newTr, newTd);
            }
            colIdx++;
        }
        for (let j = 0, len = rowspanTds.length; j < len; ++j) {
            td = rowspanTds[j];
            rspan = parseInt($B.Dom.attr(td, "rowspan")) + 1;
            $B.Dom.attr(td, { "rowspan": rspan });
        }
        this.setWnHFromDom(this.tableEl);
    }
    //打开插入表格对话框
    openInsertTable(onOKfn){       
        let $content = $B.DomUtils.createEl("<p style='padding-top:10px;line-height:50px;'>\u200b</p>");
        let $irow, $icol;
        $B.confirm({
            title: editCfg.label.inputColRow,
            content: $content,
            okFn: () => {//确认回调                   
                let prs = {
                    row: $irow.value,
                    col: $icol.value
                };
                setTimeout(() => {
                    onOKfn(prs);
                }, 10);
            },
            onClosed: () => {
                $B.DomUtils.remove($irow);
                $B.DomUtils.remove($icol);
                $irow = undefined;
                $icol = undefined;
            }
        });
        let $inputWap = $B.DomUtils.createEl(editCfg.inputColRowForm);
        $B.createTextIfr($content, $inputWap, undefined, { height: "50px" });
        if (!this.insertTableEvs) {
            this.insertTableEvs = {
                input: (e) => {
                    console.log(e.target.value);
                }
            };
        }
        $irow = $B.DomUtils.findbyId($inputWap, "row_input");
        $icol = $B.DomUtils.findbyId($inputWap, "col_input");
        $B.DomUtils.input($irow, this.insertTableEvs.input);
        $B.DomUtils.input($icol, this.insertTableEvs.input);
    }
    insertTable() {
        this.hidePanel();
        this.openInsertTable((prs)=>{
            if (this.isEmptyTd(this.clickedTd)) {
                this.removeContent(true);
                this.clearSelected();
                this.editIns.insertTableFn(prs);
            } else {
                $B.message({
                    mask: false,
                    content: '<span style="color:#9D1CF2">' + editCfg.label.insertTableMsg + '</span>',
                    timeout: 2,
                    position: 'top'
                });
            }
        });
        
    }
    removeRow() {
        this.hidePanel();
        var deleteRow = {};
        var hasLoop = this.foreachSeletedTds((td) => {
            let r = parseInt($B.Dom.attr(td, "row"));
            let row = td.parentNode;
            deleteRow[r] = row;
            let rspan = $B.Dom.attr(td, "rowspan");
            if (rspan) {
                let curRow = row;
                rspan = parseInt(rspan) - 1;
                while (rspan > 0) {
                    r++;
                    deleteRow[r] = curRow.nextSibling;
                    curRow = deleteRow[r];
                    rspan--;
                }
            }
        });
        this.makeUndoRec(this.tableEl);
        let rowNum = parseInt($B.Dom.attr(this.tableEl, "row"));
        if (hasLoop) {
            let delKeys = Object.keys(deleteRow);
            if (delKeys.length === rowNum) {
                this.removeTable();
                return;
            } else {
                delKeys.forEach((key) => {
                    this._removeRow(deleteRow[key]);
                });
            }
        } else {
            if (rowNum === 1) {
                this.removeTable();
                return;
            } else {
                this._removeRow(this.clickedTd.parentNode);
            }
        }
        clearTimeout(this._tempTimer);
        this._tempTimer = setTimeout(() => {
            if (!this.fit2parent(this.tableEl)) {
                this.setWnHFromDom(this.tableEl);
            }
        }, 10);
    }
    _removeRow(row) {
        var curRowIndex = parseInt($B.Dom.attr(row, "id").replace("row_", ""));
        var prevRow = row.previousSibling;
        var removeHeight = $B.Dom.height(row);
        var rowSpanTdArray = [];
        var childs, i, len, td, h;
        while (prevRow) {
            childs = prevRow.children;
            for (i = 0, len = childs.length; i < len; ++i) {
                td = childs[i];
                let rowspan = $B.Dom.attr(td, "rowspan");
                let rowIdx = parseInt($B.Dom.attr(td, "row"));
                if (rowspan) {
                    let rIdx = parseInt(rowspan) - 1 + rowIdx;
                    if (rIdx >= curRowIndex) {
                        rowSpanTdArray.push(td);
                    }
                }
            }
            prevRow = prevRow.previousSibling;
        }
        var newTdRec = [];
        childs = row.children;
        for (i = 0, len = childs.length; i < len; ++i) {
            td = childs[i];
            let rowspan = $B.Dom.attr(td, "rowspan");
            if (rowspan) {
                let style = $B.style2cssObj(td); // $B.Dom.attr(td, "style"); 
                style.height = parseFloat($B.Dom.attr(td, "h")) - removeHeight + "px";
                newTdRec.push({
                    style: style,
                    content: td.innerHTML,
                    col: parseInt($B.Dom.attr(td, "col")),
                    rowspan: parseInt(rowspan) - 1,
                    colspan: $B.Dom.attr(td, "colspan")
                });
            }
        }

        var nextRow = row.nextSibling;
        $B.Dom.remove(row);
        for (i = 0, len = rowSpanTdArray.length; i < len; ++i) {
            td = rowSpanTdArray[i];
            h = parseInt($B.Dom.attr(td, "h")) - removeHeight;
            let rs = parseInt($B.Dom.attr(td, "rowspan")) - 1;
            if (rs > 1) {
                $B.Dom.attr(td, { "rowspan": rs });
            } else {
                $B.Dom.removeAttr(td, "rowspan");
                //td.removeAttr("rowspan");
            }
            td.style.height = h + "px";
            td.firstChild.style.height = (h - 1) + "px";
        }
        len = newTdRec.length;
        for (i = 0; i < len; ++i) {
            let rec = newTdRec[i];
            td = Table.createTD({
                "tabindex": "0",
                "row": 0,
                "col": rec.col
            }, rec.style);
            td.innerHTML = rec.content;
            if (rec.rowspan > 1) {
                $B.Dom.attr(td, { "rowspan": rec.rowspan });
            }
            if (rec.colspan) {
                $B.Dom.attr(td, { "colspan": rec.colspan });
            }
            let idx = rec.col;
            if (idx === 0) {
                //td.prependTo(nextRow);
                $B.Dom.prepend(nextRow, td);
            } else {
                idx = idx - 1;
                let childrens = nextRow.children;
                for (let k = 0, klen = childrens.length; k < klen; ++k) {
                    let targetTd = childrens[k];
                    let _index = parseInt($B.Dom.attr(targetTd, "col"));
                    if (idx === _index) {
                        //td.insertAfter(targetTd);
                        $B.Dom.after(targetTd, td);
                        break;
                    } else if (_index > idx) {
                        let prevTd = targetTd.previousSibling;
                        if (prevTd) {
                            $B.Dom.after(prevTd, td);
                            break;
                        } else {
                            //td.insertBefore(targetTd);
                            $B.Dom.before(targetTd, td);
                            break;
                        }
                    } else {
                        let nextTd = targetTd.nextSibling;
                        if (nextTd) {
                            $B.Dom.after(targetTd, td);
                            //td.insertAfter(targetTd);
                        }
                    }
                }
            }
        }
        let rowNum = parseInt($B.Dom.attr(this.tableEl, "row")) - 1;
        $B.Dom.attr(this.tableEl, { "row": rowNum });
        this.fixRowIndex();

    }
    fixRowIndex() {
        console.log("fixRowIndex >>>>>>>>");
        let childs = this.tableEl.firstChild.children;
        for (let i = 0; i < childs.length; i++) {
            let row = childs[i];
            $B.Dom.attr(row, { row: i, id: "row_" + i });
            let tdArr = row.children;
            for (let j = 0; j < tdArr.length; j++) {
                let td = tdArr[j];
                $B.Dom.attr(td, { row: i });
            }
        }
    }
    removeCol() {
        //console.log("removeCol ......");
        this.hidePanel();
        this.makeUndoRec(this.tableEl);
        var colNum = parseInt($B.Dom.attr(this.tableEl, "col"));
        var deleteColMap = {};
        var deleteColArray = [];
        var hasLoop = this.foreachSeletedTds((td) => {
            let col = parseInt($B.Dom.attr(td, "col"));
            if (!deleteColMap[col]) {
                deleteColMap[col] = true;
                deleteColArray.push(col);
                let colspan = $B.Dom.attr(td, "colspan");
                if (colspan) {
                    colspan = parseInt(colspan) - 1;
                    while (colspan > 0) {
                        col++;
                        if (!deleteColMap[col]) {
                            deleteColMap[col] = true;
                            deleteColArray.push(col);
                        }
                        colspan--;
                    }
                }
            }
        });
        if (hasLoop) {
            if (deleteColArray.length === colNum) {
                this.removeTable();
                return;
            } else {
                for (let i = 0, len = deleteColArray.length; i < len; ++i) {
                    let rmTd = deleteColArray[i];
                    this._removeCol(rmTd);
                }
            }
        } else {
            if (colNum === 1) {
                this.removeTable();
                return;
            } else {
                let col = parseInt($B.Dom.attr(this.clickedTd, "col"));
                this._removeCol(col);
            }
        }
        $B.Dom.attr(this.tableEl, { "col": colNum - 1 });
        clearTimeout(this.tableEl);
        this._tempTimer = setTimeout(() => {
            if (!this.fit2parent(this.tableEl)) {
                this.setWnHFromDom(this.tableEl);
            }
        }, 10);
    }
    _removeCol(colIdx) {
        var resetIndexTds = [];
        var trs = this.tableEl.firstChild.children;
        for (let i = 0; i < trs.length; i++) {
            let tr = trs[i];
            let childs = tr.children;
            for (let j = 0; j < childs.length; j++) {
                let td = childs[j];
                let idx = parseInt($B.Dom.attr(td, "col"));
                let endIdx = idx;
                let colspan = $B.Dom.attr(td, "colspan");
                if (colspan) {
                    colspan = parseInt(colspan);
                    let newSpan;
                    endIdx = idx + colspan - 1;
                    if (idx === colIdx) {
                        newSpan = colspan - 1;
                    } else if (endIdx === colIdx) {
                        newSpan = colspan - 1;
                    } else if (idx < colIdx && colIdx < endIdx) {
                        newSpan = colspan - 1;
                    }
                    if (newSpan) {
                        td.firstChild.style.width = "auto";
                        td.style.width = "auto";
                        if (newSpan <= 1) {
                            $B.Dom.removeAttr(td, "colspan");
                            resetIndexTds.push(td.nextSibling);
                            break;
                        } else {
                            $B.Dom.attr(td, { "colspan": newSpan });
                            resetIndexTds.push(td.nextSibling);
                            break;
                        }
                    }
                } else {
                    if (idx === colIdx) {
                        resetIndexTds.push(td.nextSibling);
                        $B.Dom.remove(td);
                        break;
                    } else if (endIdx >= colIdx) {
                        resetIndexTds.push(td);
                        break;
                    }
                }
            }
        }
        for (let i = 0, len = resetIndexTds.length; i < len; ++i) {
            this._reduceNextTdCol(resetIndexTds[i]);
        }
    }
    _reduceNextTdCol(nextTd) {
        while (nextTd) {
            let index = parseInt($B.Dom.attr(nextTd, "col")) - 1;
            $B.Dom.attr(nextTd, { col: index });
            nextTd = nextTd.nextSibling;
        }
    }
    removeContent(notHide) {
        this.makeUndoRec(this.tableEl);
        if (notHide) {
            if (this.clickedTd) {
                let $wap = this.clickedTd.firstChild.firstChild;
                let firstp = $wap.firstChild;
                UTILS.removeAfterEls(firstp);
                firstp.firstChild.innerText = "\u200b";
                UTILS.removeAfterEls(firstp.firstChild);
                this.editIns.move2start(firstp);
            }
        } else {
            this.hidePanel();
            if (this.isSelectedTds()) {
                for (let i = 0; i < this.selectedTdArray.length; i++) {
                    let td = this.selectedTdArray[i];
                    let $wap = td.firstChild.firstChild;
                    let firstp = $wap.firstChild;
                    UTILS.removeAfterEls(firstp);
                    firstp.firstChild.innerText = "\u200b";
                    UTILS.removeAfterEls(firstp.firstChild);
                    if (i === 0) {
                        this.editIns.move2start(firstp);
                    }
                }
            } else {
                if (this.clickedTd) {
                    let $wap = this.clickedTd.firstChild.firstChild;
                    let firstp = $wap.firstChild;
                    UTILS.removeAfterEls(firstp);
                    firstp.firstChild.innerText = "\u200b";
                    UTILS.removeAfterEls(firstp.firstChild);
                    this.editIns.move2start(firstp);
                }
            }
        }
    }
    removeTable() {
        let tableEl = this.tableEl;
        if (tableEl) {
            this.makeUndoRec(tableEl);
            let $prt = tableEl.parentNode;
            $B.DomUtils.remove(tableEl);
            let $span = UTILS.createSpanEl();
            let cssObj = $B.style2cssObj($prt);
            delete cssObj.height;
            delete cssObj.overflow;
            let style = $B.cssObj2string(cssObj);
            $B.DomUtils.attr($prt, { style: style });
            $B.DomUtils.append($prt, $span);
            this.editIns.move2end($span);
            if ($B.DomUtils.hasClass($prt.parentNode.parentNode, "k_edit_td_wap")) {
                $prt.parentNode.parentNode.style.padding = "2px 2px";
                $prt.parentNode.style.width = "auto";
                $prt.parentNode.style.height = "auto";
            }
            this.onRemoved();
            this.hidePanel();
        }
    }
    /**
     * 轮询选择的td，如果不选择则为当前点击td
     * **/
    foreachCssTd(fn) {
        if (!this.foreachSeletedTds(fn)) {
            fn(this.clickedTd);
        }
    }
    foreachTdInnerPls(fn, isOnlyPel) {
        this.foreachCssTd((td) => {
            this.loopCssElInTd(td, ($p, $s) => {
                fn($p, $s, td);
            });
        }, isOnlyPel);
    }
    loopCssElInTd(td, fn, isOnlyPel) {
        let plist = td.firstChild.firstChild.children;
        for (let i = 0; i < plist.length; i++) {
            let pel = plist[i];
            if (pel.firstChild.nodeName === "TABLE") {
                this.foreachTd(pel.firstChild, (td) => {
                    this.loopCssElInTd(td, fn, isOnlyPel);
                });
            } else {
                if (isOnlyPel) {
                    fn(pel);
                } else {
                    let childs = pel.children;
                    for (let j = 0; j < childs.length; j++) {
                        fn(pel, childs[j]);
                    }
                }
            }
        }
    }
    boldFn(params, $evEl) {
        let css = UTILS.getBoldCss($evEl);
        this.foreachCssTd((td) => {
            this.loopCssElInTd(td, (pel, el) => {
                el.style.fontWeight = css;
            });
        });
    }
    italicFn(params, $evEl) {
        let css = UTILS.getitalicCss($evEl);
        this.foreachCssTd((td) => {
            this.loopCssElInTd(td, (pel, el) => {
                el.style.fontStyle = css;
            });
        });
    }
    fontColorFn(params, $evEl) {
        this.editIns.changeSelectionColor("color", params.color);
        this.foreachCssTd((td) => {
            this.loopCssElInTd(td, (pel, el) => {
                el.style.color = params.color;
            });
        });
    }
    backgroundColorFn(params, $evEl) {
        this.editIns.changeSelectionColor("background-color", params.color);
        this.foreachCssTd((td) => {
            td.style.backgroundColor = params.color;
            this.loopCssElInTd(td, (pel, el) => {
                el.style.backgroundColor = params.color;
            });
        });
    }
    fontSizeFn(params, $evEl) {
        let pMap = {};
        let tdMap = {};
        this.foreachTdInnerPls(($p, $s, $td) => {
            if (!pMap[$p.id]) {
                let data = UTILS.getLineHightData($p);
                pMap[$p.id] = { el: $p, data: data };
            }
            $s.style.fontSize = params;
            let row = $B.Dom.attr($td, "row");
            if (!tdMap[row]) {
                tdMap[row] = $td;
            }
        });
        //更新行高      
        let keys = Object.keys(pMap);
        for (let i = 0; i < keys.length; i++) {
            let $p = pMap[keys[i]].el;
            let data = pMap[keys[i]].data;
            let maxFont = UTILS.getMaxFontSize($p);
            let newHeight = maxFont * data.r + "px";
            $B.DomUtils.css($p, { "line-height": newHeight });
        }
        for (let p in tdMap) {
            this.tdfit2content(tdMap[p]);
        }
    }
    fontFamilyFn(params, $evEl) {
        this.foreachCssTd((td) => {
            this.loopCssElInTd(td, (pel, el) => {
                el.style.fontFamily = params;
                pel.style.fontFamily = params;
            });
        });
    }
    underlineFn(params, $evEl) {
        let css = "underline";
        this.textDecoration(css, $evEl);
    }
    strikethroughFn(params, $evEl) {
        let css = "line-through";
        this.textDecoration(css, $evEl);
    }
    textDecoration(css, $evEl) {
        if (UTILS.isHightLight($evEl)) {
            css = "none";
            UTILS.removeHightLight($evEl);
        } else {
            UTILS.addHightLight($evEl);
            if (css === "underline") {
                UTILS.removeHightLight($evEl.nextSibling);
            } else {
                UTILS.removeHightLight($evEl.previousSibling);
            }
        }
        this.foreachCssTd((td) => {
            this.loopCssElInTd(td, (pel, el) => {
                el.style.textDecoration = css;
            });
        });
    }
    superscriptFn(css, $evEl) {
        this.textVertical("super", $evEl);
    }
    subscriptFn(css, $evEl) {
        this.textVertical("sub", $evEl);
    }
    textVertical(css, $evEl) {
        let set = true;
        if (UTILS.isHightLight($evEl)) {
            UTILS.removeHightLight($evEl);
            set = false;
        } else {
            UTILS.addHightLight($evEl);
            if (css === "super") {
                UTILS.removeHightLight($evEl.nextSibling);
            } else {
                UTILS.removeHightLight($evEl.previousSibling);
            }
        }
        this.foreachCssTd((td) => {
            this.loopCssElInTd(td, (pel, el) => {
                if (set) {
                    el.style.verticalAlign = css;
                } else {
                    let obj = $B.style2cssObj(el);
                    delete obj["vertical-align"];
                    let attr = $B.cssObj2string(obj);
                    $B.DomUtils.attribute(el, { "style": attr });
                }
            });
        });
    }
    fontTitleFn(params, $evEl) {
        let tdMap = {};
        this.foreachCssTd((td) => {
            let r = $B.Dom.attr(td, "row");
            if (!tdMap[r]) {
                tdMap[r] = td;
            }
            this.loopCssElInTd(td, (pel, $s) => {
                $s.style.fontSize = params;
                if (params === editCfg.textFontSize) {
                    $s.style.fontWeight = "normal";
                } else {
                    $s.style.fontWeight = "bold";
                }
            });
        });
        for (let p in tdMap) {
            this.tdfit2content(tdMap[p]);
        }
    }
    fontSpaceFn(params, $evEl) {
        this.foreachCssTd((td) => {
            let pIdMap = {};
            this.loopCssElInTd(td, (pel, el) => {
                if (params.forp) {
                    let id = pel.id;
                    if (!pIdMap[id]) {
                        pIdMap[id] = 1;
                        pel.style.letterSpacing = params["letter-spacing"];
                    }
                }
                el.style.letterSpacing = params["letter-spacing"];
            });
        });
    }
    pindentFn(params, $evEl) {
        this.forPels(($p) => {
            let indent = params.indent;
            UTILS.indentPFn(indent, $p);
        });
    }
    plineHeight(params, $text) {
        let v;
        if (params["line-height"]) {
            v = params["line-height"] + "px";
        }
        let tds = {};
        this.forPels(($p) => {
            if (typeof v !== "undefined") {
                $p.style.lineHeight = v;
            } else if (params.lineR) {
                let s = UTILS.getMaxFontSize($p) * params.lineR;
                $p.style.lineHeight = s + "px";
                $text.value = s;
            }
            let td = $p.parentNode.parentNode;
            let r = $B.Dom.attr(td, "row");
            let h = this.getTdContentHeight(td);
            if (tds[r]) {
                if (tds[r].h > h) {
                    tds[r] = { el: td, h: h };
                }
            } else {
                tds[r] = { el: td, h: h };
            }
        });
        let keys = Object.keys(tds);
        for (let i = 0; i < keys.length; i++) {
            this.tdfit2content(tds[keys[i]].el);
        }
    }
    pborderFn(params, $evEl) {
        this.forPels(($p) => {
            UTILS.setBorderCss($p, params);
        });
    }
    ppadding(params, $evEl) {
        console.log("ppading ", params);
        let go = true;
        if (this.editIns.isSelected()) {
            //如果存在单元格划选的段落
            if (this.cssPelist.length > 0) {
                for (let i = 0; i < this.cssPelist.length; i++) {
                    $B.DomUtils.css(this.cssPelist[i], params);
                }
                this.tdfit2content(this.clickedTd);
                return false;
            } else {
                go = false;
            }
        }
        if (go) {//修饰td
            let tds = {};
            let go = this.foreachSeletedTds((td) => {
                this.padding2td(td, params);
                let r = $B.Dom.attr(td, "row");
                let h = this.getTdContentHeight(td);
                if (tds[r]) {
                    if (tds[r].h > h) {
                        tds[r] = { el: td, h: h };
                    }
                } else {
                    tds[r] = { el: td, h: h };
                }
            });
            if (go) {
                let keys = Object.keys(tds);
                for (let i = 0; i < keys.length; i++) {
                    this.tdfit2content(tds[keys[i]].el);
                }
            } else {
                this.padding2td(this.clickedTd, params);
                this.tdfit2content(this.clickedTd);
            }
        } else {
            return true;
        }

    }
    padding2td(td, css) {
        let key = Object.keys(css)[0];
        let $wap = td.firstChild.firstChild;
        let childs = $wap.children;
        if (key.indexOf("-top") > 0) {
            childs[0].style.paddingTop = css["padding-top"];
        } else if (key.indexOf("-right") > 0) {
            for (let i = 0; i < childs.length; i++) {
                childs[i].style.paddingRight = css["padding-right"];
            }
        } else if (key.indexOf("-bottom") > 0) {
            $wap.lastChild.style.paddingBottom = css["padding-bottom"];
        } else if (key.indexOf("-left") > 0) {
            for (let i = 0; i < childs.length; i++) {
                childs[i].style.paddingLeft = css["padding-left"];
            }
        }
    }
    getTdContentHeight(td) {
        let childs = td.firstChild.firstChild.children;
        let h = 0;
        for (let i = 0; i < childs.length; i++) {
            h = h + $B.Dom.height(childs[i]) + 2;
        }
        return h;
    }
    /**
     * td高度根据内容自动适配
     * ***/
    tdfit2content(td) {
        //console.log("tdfit2content tdfit2content");
        let trH = $B.Dom.height(td.parentNode);
        let h = this.getTdContentHeight(td);
        if (h > trH) {
            let diff = h - trH + 2;
            this.updateRowHeightByDiff(td.parentNode, diff, undefined, undefined);
        }
        //let ch = $B.Dom.height();
    }
    /**
     * 段落字体颜色
     * **/
    pcolorFn(params, $evEl) {
        this.forPels(($p) => {
            this.editIns.loopPelSapn($p, ($s) => {
                $s.style.color = params.color;
            });
        });
        this.editIns.changeSelectionColor("color", params.color);
    }
    /**
     * 段落背景色
     * ***/
    pbackground(params, $evEl) {
        this.forPels(($p) => {
            this.editIns.loopPelSapn($p, ($s) => {
                $s.style.backgroundColor = params.color;
            });
            $p.style.backgroundColor = params.color;
        });
        this.editIns.changeSelectionColor("background-color", params.color);
    }
    alignLeftFn(params, $evEl) {
        this.hAlignFn("left");
        if ($evEl) {
            $B.Dom.addClass($evEl, "k_edit_tools_hlight");
            $B.Dom.removeClass($evEl.nextSibling, "k_edit_tools_hlight");
            $B.Dom.removeClass($evEl.nextSibling.nextSibling, "k_edit_tools_hlight");
        }
    }
    alignCenterFn(params, $evEl) {
        this.hAlignFn("center");
        if ($evEl) {
            $B.Dom.addClass($evEl, "k_edit_tools_hlight");
            $B.Dom.removeClass($evEl.previousSibling, "k_edit_tools_hlight");
            $B.Dom.removeClass($evEl.nextSibling, "k_edit_tools_hlight");
        }
    }
    alignRightFn(params, $evEl) {
        this.hAlignFn("right");
        if ($evEl) {
            $B.Dom.addClass($evEl, "k_edit_tools_hlight");
            $B.Dom.removeClass($evEl.previousSibling, "k_edit_tools_hlight");
            $B.Dom.removeClass($evEl.previousSibling.previousSibling, "k_edit_tools_hlight");
        }
    }
    hAlignFn(css) {
        this.foreachTdInnerPls(($p) => {
            $p.style["textAlign"] = css;
        }, true);
    }
    vAlignTop() {
        console.log("vAlignTop ");
        this.foreachCssTd((td) => {
            td.style["verticalAlign"] = "top";
            let el = td.firstChild;
            let styleObj = $B.style2cssObj(el);
            delete styleObj.display;
            delete styleObj["align-items"];
            let style = $B.cssObj2string(styleObj);
            $B.Dom.attr(el, { style: style });
            this.alterPlistAlign(el, "auto");
        });
    }
    vAlignMiddel() {
        this.foreachCssTd((td) => {
            td.style["verticalAlign"] = "middle";
            let el = td.firstChild;
            el.style.display = "flex";
            el.style["alignItems"] = "center";
            this.alterPlistAlign(el, "100%");
        });
        console.log("vAlignMiddel ");
    }
    vAlignBottom() {
        console.log("vAlignBottom ");
        this.foreachCssTd((td) => {
            td.style["verticalAlign"] = "bottom";
            let el = td.firstChild;
            el.style.display = "flex";
            el.style["alignItems"] = "flex-end";
            this.alterPlistAlign(el, "100%");
        });
    }    
    alterPlistAlign(el, val) {
        let childs = el.children;
        for (let i = 0; i < childs.length; i++) {
            childs[i].style.width = val;
        }
    }
    static createTR(attr, css) {
        var tr = $B.DomUtils.createEl("<tr></tr>");
        if (attr) {
            $B.DomUtils.attribute(tr, attr);
        }
        if (css) {
            $B.DomUtils.css(tr, css);
        }
        return tr;
    }
    static createTD(attr, css) {
        var $p = UTILS.createPEl();
        var td = $B.DomUtils.createEl("<td contenteditable='false' id='" + $B.generateDateUUID() + "' style='vertical-align:top;box-sizing: border-box;'><div class='k_edit_td_wap' style='padding:2px 2px;width:100%;height:100%;overflow:hidden;box-sizing: border-box;'><div contenteditable='true' class='k_td_inner_wap' style='width:auto;height:auto;'></div></div></td>");
        $B.DomUtils.append(td.firstChild.firstChild, $p);
        if (attr) {
            $B.DomUtils.attribute(td, attr);
           // $p.firstChild.innerText = attr.row + "_" + attr.col;
        }
        if (css) {
            $B.DomUtils.css(td, css);
            if (css.height && css.height.indexOf("px") > 0) {
                let innerHeight = parseFloat(css.height.replace("px", "")) - 1;
                td.firstChild.style.height = innerHeight + "px";
            }
        }
        return td;
    }
    static getTable(row, col) {
        let $tab = $B.DomUtils.createEl("<table class='k_edit_table_cls' id='" + $B.generateDateUUID() + "' row='" + row + "' col='" + col + "' style='border-collapse:collapse;width:100%;height:auto;table-layout:fixed;box-sizing: border-box;'><tbody></tbody></table>");
        return $tab;
    }
}